我一直在慢慢玩MVVM,这个概念从此开始。我有一个应用程序窗口和2个用户控件,每个控件都附加了viewModels。我想点击第一个用户控件中的按钮,然后转到第二个用户控件。
这两个都在主窗口视图模型中更改屏幕,但我想在用户控件本身内完成。是否可以传递命令将窗口更改回主应用程序视图模型,或让用户控件模型更改按钮单击时的视图。
编辑:我想我需要将它作为命令传递但我不知道如何传递我想要的视图。
在MVVM中,命令通常在ViewModel级别工作,与View层无关(或任何知识)。要实现您所描述的内容,请创建一个控制您要查看的View类型的公共属性。例如(使用MVVM Light):
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;
}
}
}
如您所见,您的命令将简单地将公共属性的值操纵为适当的值。现在,您的View可以构建在此属性之上,并使用DataTrigger
s加载适当的内容:
<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>
回答你的评论:
view并没有真正与viewModel交互:这是不正确的。 View始终与VM交互,是VM对视图一无所知。关于您的困惑,请了解您不需要为每个用户控件创建一个VM。 VM是针对View而不是控件创建的。因此,您可能只有一个名为MainVM的ViewModel,它会公开您的视图将绑定到的所有公共属性。然后,每个用户控件只能使用它感兴趣的属性。然后,当底层VM的特定属性发生更改时,触发器可以将视图从一个用户控件切换到另一个用户控件。然后,新的用户控件将显示正确的数据,因为它将绑定到它想要使用的VM属性。
请记住,VM对查看视图的使用方式并不感兴趣(也没有办法)。它只需要正确地保持其状态。然后,View可以响应状态更改并相应地更新自身。