我应该改变传递给 ICommand 上 Execute 方法的参数吗?如果不是,在调用命令后更改应用程序或视图模型的状态的最佳方法是什么?
想法
命令模式调用对象上的方法,在 WPF 的情况下,它是模型或视图模型。这需要模型知道如何对自己执行操作。我们都看过并使用过 RelayCommand 实现。我遇到的问题是很难换掉行为。也很难找到放置“特殊情况”代码的地方。如果我想显示另一个视图怎么办?
我喜欢为每个用例创建一个命令的想法。我将有一个实现 ICommand 的具体类,该类处理执行用例的逻辑。这需要对模型的引用,就像命令模式一样。不同之处在于动作逻辑将在模型之外,因此会改变作为参数传入的模型。让我们看一些示例代码。
我有一个显示无处不在的 Person 对象列表的窗口。我们想在 Person 上调用一个命令来清除他们的名字。MainViewModel 有一个名为 People 的 Person 对象集合。
<Window.Resources>
<commands:ClearNameCommand x:Key="ClearNameCommand"/>
</Window.Resources>
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
这是我的列表框,它绑定到集合并显示每个人都有一个按钮来清除他们的名字。
<ListBox ItemsSource="{Binding People}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name" Width="100"/>
<TextBox Text="{Binding Name}" Width="100"/>
<Button Command="{StaticResource ClearNameCommand}" CommandParameter="{Binding}" Content="Clear"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
下面是具体类 ClearNameCommand 的 Execute 方法。它会显示一个对话框,询问他们是否要执行该操作。我认为这证明了为什么您不会将此命令放入模型中的一个很好的例子。还想象一下,您必须在某个名称被清除的地方登录?撤消重做可能?所有这些代码都去哪里了??!!
public void Execute(object parameter)
{
Person p = parameter as Person;
if (p != null)
{
if (MessageBox.Show(
"Are you sure you want to clear the name?",
"Clear Name",
MessageBoxButton.YesNo,
MessageBoxImage.Question) == MessageBoxResult.Yes)
{
p.Name = "";
}
}
}
我想您可以将所有准备代码留在命令中,然后在 Person 上调用 Clear 方法。但是,我仍然不相信这是最好的方法。如果明确改变怎么办?你最终得到 Clear2 和 Clear3 等等。更不用说每个可能的用例甚至更多的方法。
更多的想法
所以假设我有一个视图模型,它引用了一个允许传递数据绑定的模型,或者它将模型全部包装在一起。我想要摆脱的是在视图模型上为每个用例创建一个命令属性。另外,这个设计有什么好干净的?您仍在 Execute 方法中更改 Model 对象。我认为我并没有过多地弯曲命令模式。我的窗口是客户端。模型是接收者。按钮是调用者。唯一的区别是您使用调用程序注入依赖项。
稍微改一下我的问题,有没有人看到这样做的任何危险信号?
我在研究命令模式时发现了这一点。 http://msdn.microsoft.com/en-us/library/cc984279.aspx