MVVM模式中失去焦点事件策略

8
我正在使用MVVM Light Toolkit开发WPF应用程序,并绑定一个Item Control到一个组织集合。其中,组织由组织名称和列表组成,项目由项目名称、列表和新员工组成,而员工则由员工姓名、联系电话和电子邮件组成。在这种情况下,员工本身是一个可以在现有和新员工数据中重复使用的用户控件。用户可以在每个控件的“失去焦点”事件上更新现有员工的详细信息(即列表)。当涉及添加新员工时,我使用了用户控件“失去焦点”事件来处理该情况。因此,在用户控件失去焦点事件上,我使用MVVM Light Toolkit的EventToCommand将EventArgs传递给ViewModel,然后从EventArgs中查找Original Source(或通过遍历可视树)来确定是否通过检查IsKeyboardFocusWithin属性来插入它。它是否在同一用户控件内。这是否是正确的MVVM模式实现方法?另外,通过以上方法,我必须:1)遍历可视树或从EventArgs中获取Original Source,以便引用System.Windows.Controls;2)在进行单元测试时,更难模拟EventArgs。那么,是否有更好的MVVM方法来处理这种情况...

你的新员工是否绑定到视图模型中的对象?失去焦点事件是否与所有employeeUserControls相关联,还是只有针对新员工用户控件的唯一失去焦点命令? - J King
1个回答

3

正如您自己提到的那样,应该避免在ViewModel中遍历Visual Tree。

因此,这种方法的替代方案可以使用行为 - 教程

  • 假设您创建了一个名为AddNewEmployeeBehavior的行为
  • 接下来,在VM中添加一个RelayCommand<Employee> AddNewEmployeeCommand;
  • AddNewEmployeeBehavior中创建一个类型为RelayCommand<Employee>的DP
  • 在View中将行为的DP绑定到AddNewEmployeeCommand
  • 现在在AddNewEmployeeBehavior中执行与VM中相同的操作,以检查是否需要向List<Employee>添加新项
  • 当需要将新项目添加到保存在VM / Model中的List中时,请调用传递新的Employee详细信息包装到Employee对象中的DP命令的行为。
  • 在VM中,根据需要创建您的RelayCommand,以将其调用参数附加到List<Employee>

使用这种方法,您的视图中不需要任何 EventToCommand 的内容。您只需要通过一个行为将命令作为 DP 并根据您在视图上设置的条件执行命令。

至于单元测试,现在非常简单,因为您只有一个 RelayCommand,在单元测试中可以随时调用它。

由于您的 VM 中不再有任何与视图相关的逻辑,并且行为处理视图相关逻辑,因此这将作为 MVVM 解决方案。

VM -> ViewModel

DP -> Dependency Property


谢谢。我不知道我们可以使用附加行为来处理这种情况。让我练习一个样例,很快就会回复你。只是有一个小问题,就是将业务逻辑(即添加员工或不添加)保留在作为视图一部分的行为类中。 - Dennis Jose
2
@Dennis,业务逻辑不应该是行为的一部分。这里行为的目的只是向ViewModel/Model传达“嘿,我想添加一行”,而VM中的业务逻辑应该选择接受并添加或拒绝并通过ErrorTemplate通知View相应地。 - Viv
2
@Dennis,正如我在答案中提到的那样,行为应该只处理与视图相关的逻辑。只要你遵守这个原则,测试就会像我之前说的那样简单。在单元测试中,你不需要测试业务逻辑中的行为。只需尝试以不同的方式调用VM公开的命令,并验证在VM中的业务逻辑即可。 - Viv

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