C# WPF MVVM:单击按钮从一个用户控件切换到另一个用户控件

C# WPF MVVM:单击按钮从一个用户控件切换到另一个用户控件,c#,wpf,mvvm,C#,Wpf,Mvvm,我一直在慢慢地玩弄MVVM,从那时起,这个概念就开始流行起来。我有一个应用程序窗口和两个用户控件,每个控件都连接了viewModels。我想单击第一个用户控件中的一个按钮,然后转到第二个用户控件 我看过一些教程,例如: 这两种方法都在主窗口视图模型中更改屏幕,但我希望在用户控件本身中进行更改。可以传递命令将窗口更改回主应用程序视图模型,或者让用户控件模型在单击按钮时更改视图 编辑:我想我需要将其作为命令传递,但我不确定如何传递希望随它一起传递的视图 在MVVM中,命令通常在ViewModel级

我一直在慢慢地玩弄MVVM,从那时起,这个概念就开始流行起来。我有一个应用程序窗口和两个用户控件,每个控件都连接了viewModels。我想单击第一个用户控件中的一个按钮,然后转到第二个用户控件

我看过一些教程,例如:

这两种方法都在主窗口视图模型中更改屏幕,但我希望在用户控件本身中进行更改。可以传递命令将窗口更改回主应用程序视图模型,或者让用户控件模型在单击按钮时更改视图


编辑:我想我需要将其作为命令传递,但我不确定如何传递希望随它一起传递的视图

在MVVM中,命令通常在ViewModel级别工作,与视图层无关(或不了解视图层)。要实现您所描述的功能,请创建一个控制要查看的视图类型的公共属性。例如(使用MVVM灯光):

编辑 回答你的评论:

视图并不真正与viewModel交互:这是错误的。视图总是与VM交互,VM对视图一无所知。关于您的困惑,请理解您不需要为每个用户控件创建一个VM。VM是根据视图而不是控件创建的。因此,您可能会有一个名为MainVM的ViewModel,公开视图将绑定到的所有公共属性。然后,每个用户控件只能使用它感兴趣的属性。然后,当底层VM的特定属性发生更改时,触发器可以将视图从一个用户控件切换到另一个用户控件。新的用户控件将显示正确的数据,因为它将绑定到它想要使用的VM属性


请记住,VM不想(也没有办法)知道view是如何使用它的。它只需要正确地保持其状态。视图随后可以响应状态更改并相应地更新自身。

DataTemplates
用于此目的。将每个用户控件作为数据模板添加到窗口中。在ViewModel中,创建控制要查看的视图类型的公共属性。在您的窗口中,创建一个DataTrigger,用于根据此属性的值切换DataTemplate。还要了解,命令通常在ViewModel级别工作,与视图层无关(或不了解视图层)。您的命令将简单地操作公共属性的值(如上所述),视图中的DataTriggers将相应地响应以加载适当的DataTemplate。因此,我将阅读一些关于数据触发器的内容,但我认为让我困惑的是实际上切换视图的内容。用户控件1是否将数据传递给主窗口viewModel,或者用户控件1视图模型是否实际将视图更改为用户控件2。我知道视图并不真正与viewModel交互,但两个用户控件都包含在主窗口中,因此我认为主窗口viewModel实际上应该切换窗口。
class YourViewModel : ViewModelBase
{
  public string ActiveView
  {
    get { return _ApplicationMessage; }

    //Note that this setter performs notification
    set { Set(ref _ApplicationMessage, value); }
  }

  private RelayCommand<string> _SetViewCommand = null;

  public RelayCommand<string> SetViewCommand
  {
    get
    {
      if (_SetViewCommand == null)
      {
        _SetViewCommand = new RelayCommand<string>((v) =>
        {
          ActiveView = v;
        }
      }

      return _SetViewCommand;
    }
  }
}
<Button Content="Normal" Command="{Binding SetViewCommand}" CommandParameter="Normal" />
<Button Content="Edit" Command="{Binding SetViewCommand}" CommandParameter="Edit" />

<ContentControl>
  <ContentControl.Style>
    <Style TargetType="ContentControl">
      <Style.Triggers>
        <DataTrigger Binding="{Binding ActiveView}" Value="Normal">
          <Setter Property="Content">
            <Setter.Value>
              <UserControl1 />
            </Setter.Value>
          </Setter>
        </DataTrigger>
        <DataTrigger Binding="{Binding ActiveView}" Value="Edit">
          <Setter Property="Content">
            <Setter.Value>
              <UserControl2 />
            </Setter.Value>
          </Setter>
        </DataTrigger>
      </Style.Triggers>
    </Style>
  </ContentControl.Style>
</ContentControl>