0

我应该改变传递给 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

4

1 回答 1

0

我真的不知道你在说什么......你似乎有一种非常......呃,独特的与Commands合作的方式。

这需要模型知道如何对自己执行操作。

模型类中不应该有Commands ......相反,将它们放在显示该模型类的任何视图模型中。

...很难换掉行为

又是什么?不要“交换行为”。ACommand不应更改其功能。只需为每个功能创建一个。

也很难找到放置“特殊情况”代码的地方

什么是“特殊情况”代码?

如果我想显示另一个视图怎么办?

每个视图都应该有自己的视图模型。每个视图模型都应该有自己的一组ICommand对象。如果您必须LambdaRelayCommand.

想象一下,您必须在某个名称被清除的地方登录?撤消重做可能?所有这些代码都去哪里了??!!

视图模型,视图模型,视图模型。

我想您可以将所有准备代码留在命令中,然后在 Person 上调用 Clear 方法

您认为调用p.Name = ""和调用p.ClearName()执行相同操作的调用之间有什么区别?没有区别,或者最多,调用方法比直接设置属性花费的时间要长一点。

如果明确改变怎么办?你最终得到 Clear2 和 Clear3 等等

再一次……什么???会如何Name = ""改变?

虽然我希望我回答了你的一些问题,但我认为我一定在某种程度上误解了你,因为我不完全理解你的问题。请随时提出进一步的问题,但请将它们作为编辑添加到您的问题中,我将在此答案中回复,以免评论过长。


更新>>>

针对前两条评论:

是的......在几乎所有情况下,我都会为一个视图模型提供一个视图。不,我绝对没有问题将任何东西的价值从Command. 我想不出有什么理由让你认为那不行。想象一下这个场景:

在 UI 中有一个对象列表和一个编辑面板,用户可以使用它来编辑对象。您还有Button一个Command名为Duplicate. 现在,根据定义,这Command将像您所说的那样“变异”,即数据对象或模型类。

它将创建一个新对象并根据当前选定对象的值设置其属性。您是否建议这样Command做是错误的?在我看来,绝大多数Command(或方法)功能将“改变”视图中数据对象的某些属性或属性......我们如何提供这个有用的功能?

并继续“这应该在哪里?” 问题......它还能在哪里?在视图模型中,我们可以访问当前选定的项目整个项目集合。从视图模型中,我们可以访问为我们提供各种功能的任意数量的服务。您会发现很难从单独的Command课程中与其中一些东西联系起来。

于 2013-11-13T16:18:35.027 回答