【发布时间】:2011-09-02 12:37:20
【问题描述】:
在 MVVM 的各种教程中经常指定,MVVM 的目标不是消除代码隐藏,并且在代码隐藏中可能仍然需要一些事件处理。
哪些场景需要在代码隐藏中编写事件而不是在视图模型中使用命令?
【问题讨论】:
标签: .net wpf mvvm command code-behind
在 MVVM 的各种教程中经常指定,MVVM 的目标不是消除代码隐藏,并且在代码隐藏中可能仍然需要一些事件处理。
哪些场景需要在代码隐藏中编写事件而不是在视图模型中使用命令?
【问题讨论】:
标签: .net wpf mvvm command code-behind
我没有找到一个很好的方法来处理绑定列表框中的多个项目的选择,并且必须在后面的代码中完成。但这不是“不干净”
【讨论】:
您总是会遇到纯粹主义者说代码隐藏文件中不应该有任何代码。我通常是一个纯粹主义者,但在这种情况下不是。
如果您有非常特定于视图的逻辑,它应该放在代码隐藏文件中。当我编写复杂的视图需要根据属性或视图模型的变化对可视化树的结构进行较大的更改时,我会将这段代码放在视图中。视图模型不应该对视图一无所知,因此它不能(也不应该)直接控制这些更改。有时这些更改可以通过 Style 或 DataTemplate 中的触发器来实现,但有时好的老式代码是最好的方法。
【讨论】:
根据我的经验,使用不支持 MVVM 绑定的第 3 方控件会导致在代码隐藏文件中编写代码。即使对于简单的用法(例如选择当前项目、读取当前选定的项目等)也会发生这种情况,这在控件中实现起来应该相当简单,但实际上并没有。
Silverlight TreeView 控件的 SelectedItem 属性就是一个示例,它不是 DependencyProperty(可绑定)而是常规属性,因此您无法绑定。
正如@BoltClock 所提到的,有时将一些代码放在与视图所做的真正相关的代码中似乎是合乎逻辑的,并且与视图“背后”的逻辑无关。最好将这些逻辑放在代码隐藏中。
【讨论】:
我想说,如果您要移植到另一个桌面 UI(例如 mac),任何需要不同的“逻辑”都应该在后面的代码中。 (例如,具有大致相同逻辑 UI 需求的其他平台)
因此,当用户“悬停”在输入字段上时,挂钩所有事件以分离应该在后面的代码中,但是当用户悬停时决定在“状态行”中显示什么应该在视图模型中.
【讨论】:
我遇到的一种情况是使用 3 方控件。一些 3'rd 方控件(如 telerik grid)在内部使用自己的自定义数据类型来表示网格行等,您需要处理各种网格事件以将这些 UI 特定类型转换为您的自定义类型,然后将它们传递给 VM。
【讨论】:
我认为自定义用户控件有可能使用背后的代码。
假设您创建了一个继承 TabItem 的 Closable Tab Item 类。您可以使用事件处理该关闭操作并将其绑定到 DP。
这当然是通用的,可以多次使用。
所以我猜当事件与 UI 而不是 dataModel 或其他活动有关时,后面的代码是可以接受的。
【讨论】:
通常,如果您的代码与 UI 逻辑相关,请将其保存在视图的 XAML 或代码隐藏中。视图模型只负责视图和模型之间的桥接和绑定数据。
可以在我的一个问题How do I make a WPF window movable by dragging the extended window frame? 中找到一个示例,我使用的事件之一是SourceInitialized,我在其中访问Window 的窗口句柄以执行一些Windows API 魔术。但是这一切都与窗口有关,与窗口之外的应用程序逻辑无关,所以我将其全部限制在窗口的代码隐藏文件中,让视图模型完全不知道。
【讨论】:
在我看来,在 MVVM 中,当与 UI 相关的事件,比如动画,你可以写在代码隐藏文件中。
所有业务逻辑都应该在视图模型中。
【讨论】: