Behaviors和ViewModels在MVVM中有什么关系?

7
我在学习MVVM时遇到了一个问题。我有一个TreeView,其中包含TextBlocks,我想在双击TreeView中的任何TextBlock时执行某个操作。我开始学习Behaviors,并且有一个很好的示例说明如何实现行为,但是该示例根本没有将Behavior连接到ViewModel。换句话说,如果我双击TextBlock,我有捕获它的Behavior类,但我没有任何ViewModel来执行任何操作。
请问有人可以花一点时间解释这些是如何联系的吗?我正在查看此文章: http://msdn.microsoft.com/en-us/library/gg430869(v=pandp.40).aspx 但我似乎没有理解我要寻找的内容。
2个回答

9
MVVM概念为我们提供了一种在WPF应用程序中的解耦机制,这意味着xaml.cs文件中不再有代码。附加行为是不同的东西。它与MVVM无关。
但是因为我们有一些情况下不能使用MVVM,例如双击选择TextBox文本。这是您想要添加到textbox的行为。
您会更喜欢在xaml.cs文件中实现双击功能,因为它不可重用并且紧密耦合。
这就是行为出现的地方。我们将为TextBox创建行为并将其附加。现在,您可以将此行为附加到任意数量的控件上。
编辑:
如果您使用的是WPF 4.5,则可以查看事件的标记扩展 如果您想使用附加行为来完成此操作,请创建一个双击事件的附加行为,该行为具有命令依赖属性。您的双击行为只需引发所附加的命令,然后在xaml中将命令绑定到视图模型,我希望您知道如何执行。
希望我能够回答您的评论。

1
D J - 我创建的 Behavior 类与 ViewModel 本身没有任何关系吗?例如,我有一个 TreeView,当我双击 TreeView 中的节点时,我想删除该节点。当我在 Behavior 类中捕获 DoubleClickEvent 时,我无法访问 TreeView 中的 ItemsSource(存储在 ViewModel 中)。 - Tada

3

D J提供了一个好的答案,不过我想在这个讨论中补充一些额外的想法。

根据我的经验,当视图不依赖于视图模型才能正常运行时(无论是代码后台、附加行为、混合行为还是自定义控件逻辑),视图行为通常很有用。如果一个视图(UserControlWindowPage等)在没有视图模型的情况下在逻辑上没有意义,那么将行为从视图中删除并将其移动到视图模型中可能更有意义。

虽然我们可以使用各种类型的行为做任何事情,但通常不明智。MVVM出于良好的原因限制了我们应该做什么,以便我们可以观察关注点分离,以提高应用程序的凝聚力并解耦我们的类。这两个概念是软件可维护性的全部,随着应用程序发展为企业软件,这些概念变得越来越重要。

重要的是要考虑行为所涉及的关注点。了解这一点将有助于我们找到一个合适的位置。以下是一些问题,可以帮助我们确定它属于哪个位置:

该行为是否与业务领域模型交互(这是MVVM中的第一个'M')?

具有对领域模型的依赖性(即使是松散耦合的依赖性)的行为可能应该属于视图模型(或服务),而不应该属于视图。例如,如果行为需要保存到外部设备(例如数据库)或从外部设备读取,它就具有了视图不应该具有的依赖性。将此逻辑包装在服务函数中。或者如果不使用高度分层的架构,则将其放在视图模型内部。

该行为是否与应用程序服务、领域服务、基础结构服务等交互?

出于与前一个答案相同的原因,该行为可能应该属于视图模型或服务类。视图不应该明确知道服务或领域模型对象,因为这会使其责任(或关注点)变得混乱。视图只应关注用户UI的可视/物理方面。许多视图应定义一个协议(即视图模型接口),以便正确地绑定到它。

该行为是否需要在同一类型的不同视图之间重用?

这是一个有点棘手的问题。许多时候,我们预见到能够为相同内容提供不同的呈现方式。实际上,在这些情况下,视图是一种围绕某个结构的薄包装器。例如,假设对于电子邮件应用程序,我们有一个接收电子邮件的摘要视图和一个详细视图。两个视图都可能需要支持相同的行为(例如删除、回复、转发)。因为我们在同一类型的不同视图之间重用了行为,所以行为应该属于一个通用的可重用位置。视图模型逻辑是一个好的地方。

该行为是否需要在不同类型的视图之间重用?

当行为需要在不同类型的视图中重复使用时(例如TextBoxComboBox),我们可能需要一个附加行为。通常,我们可以知道这一点,因为视图是如此多样化,以至于它们不可能共享视图模型接口。鉴于该行为涉及与视图相关的职责,则自定义控件逻辑、代码后台、附加行为或混合行为都是合适的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接