谁应该在 WPF/MVVM 中调用 VIewModel 逻辑单元或视图

本文关键字:VIewModel 单元 视图 调用 WPF MVVM | 更新日期: 2023-09-27 18:31:08

我的问题是"最佳实践是什么?"类型,在非常特殊的情况下:

我有一个包含复选框列表框的视图。

列表框。ItemsSource 绑定到 ViewModel(人员列表)中的集合。和每个复选框。IsChecked 绑定到 Person.IsSelected

选中

/取消选中复选框会激活 ViewModel 中的"刷新"方法,该方法可能会也可能不会重新设置 Person.IsCheck 的所有人。当然,这应该通知 UI Person.IsChecked(可能已经)已更改。

我的问题是:谁应该负责调用ViewMode.Refresh?UI 是否应该通过事件或命令调用该方法?或者视图模型应该亲自订阅适当的事件。

谁应该在 WPF/MVVM 中调用 VIewModel 逻辑单元或视图

如果 UI 绑定到 IsChecked ,则无需通知它。或者,更确切地说,WPF 本身会通知它。这是MVVM的吸引力之一。视图模型可以根据自己的规则集简单地更新其状态,视图通过绑定自动接收这些更改。

取决于你所说的"call"是什么意思

以下是答案

如果您的意思是创建:

  • 其他视图模型
  • 任何不是视图或模型的东西(因为它们都不应该知道你的 VM)

如果你谈论执行一个方法:

  • 自我执行(例如,在属性更改、命令等之后)
  • 其他视图模型
  • 任何不是视图或模型的东西(因为它们都不应该知道你的 VM)

在您的情况下也很重要:

您说您的列表绑定为"收藏"
在这里你可能会遇到一些麻烦,因为你的视图改变了Person.IsSelected,这应该为你的 IsSelect 引发一个属性更改。
现在它将卡住,因为如果您的 Item 属性已更改,这是一个已知问题ObservableCollection不会收到通知。要解决此问题,您需要将INotifyPropertyChanged事件连接到ObservableCollection中的CollectionChanged事件。因此,它可以冒泡到您的 VM,并且可以执行他的Refresh()

在这里,您可以看到如何做到这一点的示例。

我想你必须问问自己,"刷新"的回应是什么?

如果它响应实际单击的复选框,则视图负责调用它。

如果是为了响应被选中的人员,则视图模型应监视其自己的集合,以了解对 IsSelected 的更改。

我同意MehaJain的观点,后者更难设置,但替代方案打破了层之间单个工作单元的责任,这意味着需要在导致IsSelected更改的任何其他函数中复制逻辑。这包括绑定到相同信息的其他视图、其他命令(假设您有一个用于运行选择特定人员的筛选器的按钮)和测试。

我更愿意通过事件或命令刷新视图模型。

因为订阅集合成员很棘手。假设您要使用第二种方法:订阅 Person 类更改事件。然后它可能有以下缺点:

  • 在视图模型的构造函数中,您必须订阅列表中的每个"Person"成员。
  • 在视图模型中,每当修改集合时,您必须订阅/取消订阅该列表的添加/删除成员。
  • 在释放视图模型时,您必须取消订阅已更改事件的订阅。

因此,如果您要订阅 Person 类的更改事件,这是一个开销。