使用传统点击事件和ICommand是反模式吗?

时间:2015-07-23 20:00:43

标签: c# wpf mvvm

通常,我认为使用ICommands来处理需要执行某些操作的按钮点击(例如保存用户输入)是一种很好的做法。但是,当按钮在UI上严格执行某些操作时,例如打开模式对话框,视图模型不需要处理它,甚至不知道它发生了。在这种情况下,似乎只使用按钮的Click事件处理程序更有意义,但混合和匹配就像是一个潜在的反模式。我这么认为是正确的吗?

例如:

var openModalButton = new Button();
openModalButton.Click += OnModalButtonClick;

//Elsewhere in the view...
var saveInputButton = new Button { Command = _vm.SaveInput };

通过查看代码使用命令的原因以及使用click事件的原因,这本身并不清楚。

3 个答案:

答案 0 :(得分:3)

当然,罗宾指出,一致性很重要。但是,有些情况下您不希望ViewModel参与其中。然后就没有选择了,我认为在这里打破一致性要好得多,但不要通过处理ViewModel中不是它的工作的东西来打破模式(MVVM)。

您以模态对话框为例,我不同意ViewModel不应该知道它。当然,ViewModel不允许直接打开该对话框,设置其所有者等。但是对话框很可能是工作流程的一部分,了解ViewModel中工作流程的当前状态就可以了。所以中间应该有一层。一种服务或类似的东西,允许你说"我想显示X"并通过使用模态对话框解决了这个问题。 ViewModel不知道模态对话框,但它知道当前状态,例如它询问用户是否保存更改。当然,这需要某种基础设施来处理特殊情况和棘手的部分。 MVVM框架为此提供了解决方案。

如果对您的应用程序来说听起来有点过分,只需将该事件处理放在视图后面的代码中即可。它不是很漂亮的风格,但它不会打破MVVM模式。

用一句话来说:混合比违反模式更好。

答案 1 :(得分:2)

杰迪戴亚,

我通常会像你一样混合搭配。通常(对我而言)只有1或2个这样的情况,模式和架构的想法是使代码更容易阅读和简化。为了确保遵循MVVM模式,添加大量代码似乎使这种情况下的事情变得复杂。也就是说,我通常处理的方式是使用ICommand将按钮绑定到ViewModel,然后使用" mediator"或者"服务"启动对话框。您可以通过以下方式进行Google搜索:" HOw可以处理以mvvm方式打开模式对话框"和/或看:

Open dialog in WPF MVVM

The "pretty" way to make a modal dialog in WPF with Prism and MVVM Pattern

Handling Dialogs in WPF with MVVM

祝你好运!

戴夫

答案 2 :(得分:0)

我认为这是一种反模式,或者至少不是很酷的事情,首先是因为你混合了这两种方法并且这种方法并不一致,其次是因为我认为这需要总是在命令而不是命令中处理事件处理程序,为什么?

  

视图模型不需要处理它,甚至不需要知道它   发生了。在这种情况下,使用它似乎更有意义   按钮的Click事件处理程序

不是真的,除了命令帮助你将对象与执行Command的逻辑分开,因此它使它松散耦合,但它也有助于增强代码的可重用性,例如将来可能想要的人将该按钮更改为可能具有不同事件的全新控件,以及相应事件的不同args ... 并且这会破坏您的代码,但是使用命令会更好并且始终兼容且可重复使用。

此外,Laurent Bunion在this article中解释了事件是如何成问题的:

  

对于他们所有的实用程序,事件处理程序有一个有问题的方面   效果:它们可以在实例之间创建紧密耦合   公开事件和订阅它的实例。系统   需要跟踪事件处理程序,以便它们可以执行   引发事件时,但这可能会创建强大的链接   防止垃圾收集。当然,如果这不是问题   事件处理程序是一个静态方法,但并不总是可行   仅使用静态方法处理所有事件。这是一个常见的原因   对于.NET中的内存泄漏。

     

事件与其之间紧密耦合的另一个后果   handler是在XAML中声明的UI元素的事件处理程序   必须在附加的代码隐藏文件中找到。如果它不存在(或   如果没有附加的代码隐藏文件),编译将失败   有错误。使用list时尤其如此   控件和关联的DataTemplates。当模板的一个元素   必须启动,可以定义事件处理程序,但作为一个   结果,DataTemplate无法移动到外部   的ResourceDictionary。