WPF:MVVM在哪里停止并且代码隐藏开始了?

时间:2011-04-06 20:30:43

标签: wpf mvvm code-behind

我创建了一个窗口,其中有一个ListView来显示一组人物。还有3个TextBox es应该显示人的姓名和年龄。最后,有Button来保存在TextBox es中输入的新人数据。

通过实施MVVM将人员加载到ListView中。奇迹般有效!此外,通过单击Button将新人添加到集合中也是通过MVVM完成的。

但有两个用例,我不确定使用命令是更明智的,即MVVM,还是简单的代码隐藏。用例是:

  1. 当用户从ListView中选择一个人时,TextBox es应该显示该人 细节。
  2. 当用户键入类型字符而不是显示的TextBox中的数字时 在这个人的年龄,应该警告他或她输入的数据不正确。
  3. 我怀疑是否应该使用MVVM或代码隐藏的原因是因为两个用例都与仅查看(GUI)相关,即没有与模型或应用程序业务逻辑的交互性。 ListView项源被绑定到一组人ObservableColleciton<Person>,并且当填充ListView时,与所选人员相关的所有数据已经​​传递到视图与项目。在第二个用例中,再次,没有必要转到ViewModel,以便让它触发有关错误用户输入的消息框。如何在ViewModel类的 age 依赖项属性中创建验证回调呢?

    感谢所有澄清。

4 个答案:

答案 0 :(得分:6)

当ListView选择发生变化时,文本框可以而且绝对应该通过XAML中的绑定填充,例如:

<ListView Name="people" .../>

<TextBox Text="{Binding ElementName=people, Path=SelectedItem.FirstName}"/>

或者为了减少编码,使用DataContext集将文本框放在各自的面板中,例如:

<Grid DataContext="{Binding ElementName=people, Path=SelectedItem}">
    <TextBox Text="{Binding Path=FirstName}"/>
    <TextBox Text="{Binding Path=LastName}"/>
</Grid>

验证可以在XAML中连接,但执行验证的代码通常在类中实现。 System.Windows.Controls中有一个名为ValidationRule的方便抽象类,可用于快速创建验证器。有关示例,请参阅this blog post

答案 1 :(得分:6)

我开始将代码放入代码隐藏文件的唯一一次是我无法将其放在ViewModel中或更深入的对象图中。

例如,如上所述C. Lawrence Wenham,您首先在XAML代码中完全可以解决问题。没有必要求助于代码隐藏来实现这种效果。此示例可以扩展为与集合的交互,集合不一定在像列表框这样的控件中呈现。您可以编写XAML代码,通过绑定响应ViewModel中集合中当前项的更改。

您的第二种情况也可以通过ViewModel中的dvalidation工具实现,并使用您的XAML数据绑定到这些工具。 IDataErrorInfo是一个很好的机制,内置于此目的。 Here is a nice little article演示了IDataErrorInfo的简单使用。

当你不得不陷入代码隐藏的时候,希望很少和很远。我遇到的一个例子是当一个控件不支持ICommand而你无法将功能绑定到一个行为元素时,一个示例控件就是一个ListBox。但是有一些技术可以解决这个限制,as demonstrated in this great SO question。此外,如果您需要在自定义控件中覆盖渲染,则需要在代码隐藏或继承的类中执行此操作。

希望这会为答案添加更多有用的信息。

答案 2 :(得分:2)

您可以使用validation rule进行绑定。它不会显示消息框(尽管可能会显示),但您可以定义显示错误的ErrorTemplate

答案 3 :(得分:2)

MVVM背后的主要动机是关注点的分离,即与呈现分离的逻辑。 你所描述的内容(搜索和验证)对我来说看起来更“逻辑”,所以我会把它放在ViewModel中(假设当然不能用数据绑定来执行)。

  • 请记住,视图很难测试,因此,如果您实现的逻辑可能存在重大错误,那么将其置于viewModel中是理由。

  • 一种替代(半严肃但通常有效)的方法来判断某些东西是属于模型还是属于viewModel,问自己如果将视图(Window,UserControl或其他)提供给你的话会发生什么平面设计师(即使你没有,假装你这样做)。如果你可以认为他可以将他的c#-incompetent [*]手放在后面的代码上(并弄清楚它),这通常表明代码严格与表示相关并且可以安全地存在于视图。 大多数情况下,您最终会将其移至ViewModel。

[*]只是出于教育目的而说,许多设计师比我更有能力: - )