WPF Mutate命令模式

时间:2013-11-13 15:43:31

标签: wpf command-pattern

我应该改变在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等等。更不用说针对每个可能的用例或甚至更多的方法。

更多想法

所以,假设我有一个View Model,它引用了一个Model,允许传递数据绑定或者将Model包装在一起。我想要摆脱的是在View Model上为每个用例创建一个Command属性。那个设计真是太干净了?您仍然在Execute方法中改变Model对象。我认为我没有那么多弯曲命令模式。我的窗口是客户端。模型是接收者。而按钮是祈求者。唯一的区别是你正在向调用者注入依赖项。

稍微改一下我的问题,有没有人看到这样的红旗?

我在研究命令模式时发现了这一点。 http://msdn.microsoft.com/en-us/library/cc984279.aspx

1 个答案:

答案 0 :(得分:0)

我真的不知道你在谈论什么......你似乎有一种非常独特的方式与Command合作。

  

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

模型类中绝不应包含Command ...而是将它们放在显示该模型类的任何视图模型中。

  

......交换行为很困难

再次......什么?不要'换掉行为'。 Command不应更改其功能。只需为每个功能创建一个。

  

找到一个放置“特殊情况”代码

的地方也很困难

什么是“特例”代码?

  

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

每个视图都应该有自己的视图模型。每个视图模型都应该有自己的ICommand个对象集。如果您必须在Lambda中复制少量RelayCommand表达式,那真的不是问题。

  

想象一下你必须在名称被清除的地方登录?撤消重做也许??所有这些代码都在哪里?? !!

查看模型,视图模型,视图模型。

  

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

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

  

如果有明显变化怎么办?你最终得到Clear2和Clear3等等

再次......什么??? Name = ""将如何改变?

虽然我希望我回答了一些你的问题,但我认为我必须以某种方式误解了你,因为我不完全理解你的问题。请随时提出进一步的问题,但请将其添加为您的问题的编辑内容,我将在此回答中回复,以便评论不会变得荒谬。


更新&gt;&gt;&gt;

回应前两条评论:

是的......几乎在所有情况下,我都会有一个视图模型的视图。不,我从Command更改任何的值绝对没有问题。我想不出你为什么认为那不行的任何理由。想象一下这种情况:

UI中有一个对象列表和一个编辑面板,用户可以使用它来编辑对象。您还有一个ButtonCommand名为Duplicate。现在,根据定义,Command将在您调用它,数据对象或模型类时“变异”。

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

继续'这应该在哪里?'问题......它还能在哪里?在视图模型中,我们可以访问当前所选项目整个项目集合。从视图模型中,我们可以访问为我们提供各种功能的任意数量的服务。您会发现很难从单独的Command类中连接其中的一些内容。