WPF导航标头MVVM

nbnkbykc  于 2022-12-27  发布在  其他
关注(0)|答案(2)|浏览(188)

我需要你们的提示,我希望有人能帮助我。
我想做一个有导航头的WPF应用程序。
导航标题的意思是:我想在顶部有一个包含按钮的网格,当你点击按钮时,底部的网格应该显示一个完全不同的视图。这些视图也可以包含按钮,当点击这些按钮时,只有底部的网格应该更新,顶部应该保持原样。
我也想在我的应用程序中使用MVVM。
下面的代码中,你可以更好地理解我的意思
'

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow"
        Height="450"
        Width="800">

     <Grid>
          <Grid.RowDefinitions>
               <RowDefinition Height="Auto" />
               <RowDefinition Height="*" />
          </Grid.RowDefinitions>

          <Grid Grid.Row="0" Background="Red"> <!--this should be the header for the application-->
               
               <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
               </Grid.ColumnDefinitions>

               <Button Grid.Column="0" Content="View 1" Margin="4"/>
               <Button Grid.Column="1" Content="View 2" Margin="4"/>
               
          </Grid>

          <Grid Grid.Row="1" Background="LightBlue">
               <Label Content="View 1/ View 2 Content" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
          </Grid>

     </Grid>

</Window>

'
enter image description here

avkwfej4

avkwfej41#

这是一个开端:将每个视图封装在一个Grid中,并在视图模型中管理它们的可见性。如果您从MVVM开始,这是一个简单的解决方案。

主视图

<Window x:Class="NavigationHeader.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NavigationHeader"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConv" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Background="Red">
            <!--this should be the header for the application-->

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Button Grid.Column="0" Content="View 1" Margin="4" Command="{Binding View1Command}"/>
            <Button Grid.Column="1" Content="View 2" Margin="4" Command="{Binding View2Command}"/>

        </Grid>

        <Grid Grid.Row="1" Background="LightCoral" Visibility="{Binding View1Visibility, Converter={StaticResource BoolToVisConv}}">
            <StackPanel>
                <Label Content="View 1" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                <TextBox Text="my content" Width="100" Margin="10"/>
                <Button Content="Ok" Width="50" Margin="10"/>
            </StackPanel>
        </Grid>

        <Grid Grid.Row="1" Background="LightBlue" Visibility="{Binding View2Visibility, Converter={StaticResource BoolToVisConv}}">
            <Label Content="View 2" FontSize="24" HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>

    </Grid>
</Window>

主虚拟机

对于视图模型,您需要安装Nuget的包CommunityToolkit.Mvvm,因为主VM需要这些命名空间:

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

public class MainVM : ObservableObject
{
    private bool myView1Visibility;
    private bool myView2Visibility;

    public MainVM()
    { 
        myView1Visibility = false;
        myView2Visibility = false;
    }

    public bool View1Visibility
    {
        get { return myView1Visibility; }
        set
        {
            if (value == myView1Visibility) return;

            myView1Visibility = value;
            OnPropertyChanged(nameof(View1Visibility));
        }
    }

    public bool View2Visibility
    {
        get { return myView2Visibility; }
        set
        {
            if (value == myView2Visibility) return;

            myView2Visibility = value;
            OnPropertyChanged(nameof(View2Visibility));
        }
    }

    RelayCommand myView1Command;
    RelayCommand myView2Command;

    public RelayCommand View1Command
    {
        get
        {
            if (myView1Command == null)
                myView1Command = new RelayCommand(View1CommandAction);

            return myView1Command;
        }
    }

    public RelayCommand View2Command
    {
        get
        {
            if (myView2Command == null)
                myView2Command = new RelayCommand(View2CommandAction);

            return myView2Command;
        }
    }

    private void View1CommandAction()
    {
        View2Visibility = false;
        View1Visibility = true;
    }

    private void View2CommandAction()
    {
        View1Visibility = false;
        View2Visibility = true;
    }
}

在Main的View代码背后示例化VM:

public partial class MainWindow : Window
{
    private readonly MainVM myMainVM;

    public MainWindow()
    {
        InitializeComponent();
        myMainVM = new MainVM();
        DataContext = myMainVM;
    }
}
lstz6jyr

lstz6jyr2#

除了Yannick为可见性转换器指出的内容外,我还将做以下工作。
创建两个额外的“UserControl”类(类似于窗口的xaml标记,但是让每个用户控件绘制IT所要表示的内容。这样,如果你需要移动这些内容,你就可以修复那个控件。它仍然驻留在你的外部主窗口中。例如。

<Window x:Class="NavigationHeader.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NavigationHeader"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisConv" />
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>

        <Grid Grid.Row="0" Background="Red">
            <!--this should be the header for the application-->

            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>

            <Button Grid.Column="0" Content="View 1" Margin="4" Command="{Binding View1Command}"/>
            <Button Grid.Column="1" Content="View 2" Margin="4" Command="{Binding View2Command}"/>

        </Grid>

        <local:MyFirstControl
           Grid.Row="1" 
           Background="LightCoral" 
           Visibility="{Binding View1Visibility, 
                         Converter={StaticResource BoolToVisConv}}"  />       

        <local:MySecondControl
           Grid.Row="1" 
           Background="LightBlue" 
           Visibility="{Binding View2Visibility, 
                         Converter={StaticResource BoolToVisConv}}" />

    </Grid>
</Window>

<UserControl x:Class="NavigationHeader.MyFirstControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NavigationHeader"
        mc:Ignorable="d" >
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="50" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
  
        <Label Grid.Row="0" Grid.Column="0"
            Content="View 1" FontSize="24" 
            HorizontalAlignment="Center" VerticalAlignment="Center"/>

         <TextBox Grid.Row="0" Grid.Column="1"
             Text="my content" Width="100" Margin="10"/>
         
         <Button Grid.Row="2" Grid.Column="2"
             Content="Ok" Width="50" />
    </Grid>
</UserControl>

<UserControl x:Class="NavigationHeader.MySecondControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:NavigationHeader" >
    <StackPanel>
        <Label Content="View 1" 
             FontSize="24" 
             HorizontalAlignment="Center" VerticalAlignment="Center"/>
        
        <TextBox Text="my content" Width="100" Margin="10"/>
        
        <Button Content="Ok" Width="50" Margin="10"/>
    </StackPanel>
</UserControl>

请注意,主窗口引用了另外两个类,您可以将其创建为用户控件MyFirstControlMySecondControl。这有助于保持每个控件中的混乱状态,而不是使主控件膨胀,并担心不同的格式,例如一个使用网格,另一个使用堆栈面板、对接面板或任何其他类型的控件。

相关问题