c# - 如何在 MVVM 项目中的用户控件之间切换

标签 c# wpf mvvm binding inotifypropertychanged

编辑:尽管这个问题已被 @AbinMathew 标记为可能与 this 重复。 ,为该问题提供的解决方案没有很好地解释如何中继命令逻辑。正如我的回答中提到的,我能够在约翰·史密斯的文章的帮助下解决这个问题。

我正在运行这个测试项目,以便了解 MVVM。我想要实现的目标:MainWindow 有一个后退按钮和一个 ContentControl。在 Window_loaded 上,我想在 ContentControl 中显示 MainGadget。当我在 MainGadget 中单击 MyBtn 时,我想在 ContentControl 中显示 MyGadget。

ViewModelBase 是 MainGadgetVM、MainWindowVM 和 MyGadgetVM 使用的类。它实现 INotifyPropertyChanged 接口(interface)。 RelayCommand 实现了 ICommand 接口(interface),因此我想用它来执行 MyBtn_Click 并显示其他 UserControls。

目前,当我运行该程序时,仅显示“后退”按钮。我似乎无法弄清楚如何显示其他用户控件。任何帮助将不胜感激。

Solution Explorer

数据模板.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:vm="clr-namespace:ExampleContentCtrl.VMs"
                    xmlns:view="clr-namespace:ExampleContentCtrl.Panels">
    <DataTemplate DataType="{x:Type vm:MainGadgetVM}">
        <view:MainGadget/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type vm:MyGadgetVM}">
        <view:MyGadget/>
    </DataTemplate>

</ResourceDictionary>

MainWindow.xaml

<Window x:Class="ExampleContentCtrl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="375" Width="300" Loaded="Window_Loaded">
    <Window.Resources>
        <ResourceDictionary Source="DataTemplates.xaml"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="8*"/>
        </Grid.RowDefinitions>
        <Button x:Name="BckSpace" Content="Back" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0"/>
        <ContentControl Grid.Row="1"/>
    </Grid>
</Window>

MainGadget.xaml

<UserControl x:Class="ExampleContentCtrl.Panels.MainGadget"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Button x:Name="MyBtn" Content="My Gadget" HorizontalAlignment="Center" VerticalAlignment="Top" Grid.Row="1" Command="{Binding MyBtn_Click}"/>
    </Grid>

</UserControl>

MainWindow.xaml.cs

namespace ExampleContentCtrl
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //Load MainGadgetVM via MainWindowVM.Initialize()
        }

    }
}

MainWindowVM.cs

namespace ExampleContentCtrl.VMs
{
    public class MainWindowVM : ViewModelBase
    {
        private RelayCommand _ShowWorkSpace;
        private static MainWindowVM _Instance;
        public static MainWindowVM Instance { get { return _Instance; } }

        public MainWindowVM()
        {
            MainWindowVM._Instance = this;
        }

        public RelayCommand ShowWorkSpace
        {
            get
            {
                if (_ShowWorkSpace == null)
                    _ShowWorkSpace = new RelayCommand(param => { });
                return _ShowWorkSpace;
            }
        }

        public void Initialize()
        {
            //this.ShowWorkSpace.Execute("ExampleContentCtrl.VMs.MainGadgetVM");
        }
    }
}

最佳答案

向您的内容控件添加绑定(bind),并将绑定(bind)值更改为您要显示的 View 模型。

<Window x:Class="ExampleContentCtrl.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="375" Width="300" Loaded="Window_Loaded">
    <Window.Resources>
        <ResourceDictionary Source="DataTemplates.xaml"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="8*"/>
        </Grid.RowDefinitions>
        <Button x:Name="BckSpace" Content="Back" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0"/>
        <ContentControl Grid.Row="1" Content={Binding Path=MyContent}/>
    </Grid>
</Window>


public class MainWindowVM  
{
    //...

    public MainViewModel
    {
        MyContent = new TheViewModelThatShouldBeShownAtStart();
    }

    public object MyContent
    {
        get; private set; // add Notification!
    }


    void FunctionCalledWhenButtonIsPressed()
    {
        if (...) // add your logic here
            MyContent = new VM1();
        else
            MyContent = new VM2();
    }

}

关于c# - 如何在 MVVM 项目中的用户控件之间切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32230086/

相关文章:

c# - 是否可以使用 c# 类创建此 JSON 格式?

c# - 使用 Pbkdf2 加密通过 Salt 加密和验证哈希密码

wpf - 重用内置 WPF 样式

wpf - 相对源与元素名称

WPF ProgressBar 不更新

c# - 将 INotifyPropertyChanged 添加到模型?

c# - 将 Entity Framework 对象实例持久化到 xml

c# - 如何在 WebApi 中设置全局错误处理程序?

c# - 如果值为空则更改绑定(bind)

c# - WPF - 集合中属性的 OnPropertyChanged