处理ViewModel中的WPF对象

时间:2010-03-05 09:36:10

标签: .net wpf mvvm

使用MVVM模式创建WPF应用程序,您可以使用ViewModel向View提供数据。我遇到了一种情况,我觉得在我的ViewModel中创建WPF对象是合理的,而View会抓取这些并显示它们。更具体地说,我具有绘制最终需要存储InkPresenter的功能。我在视图的代码隐藏中接收鼠标手势,但将事件传递给ViewModel。 ViewModel处理鼠标事件并创建放置在ObservableCollection中的绘图对象,以便View可以将它们取出并显示它们。

问题是;这没关系,或者在ViewModel类中创建WPF对象是不好的做法?为什么?如果可以的话;处理这些物品有什么最佳做法或建议吗?

2 个答案:

答案 0 :(得分:2)

不,它是“不好”(引用我正在谈论最佳实践 - 说ViewModel不是ViewModel,因为它确实是错误的)在ViewModels中创建和引用WPF(Control-)类。

当您尝试对ViewModel进行单元测试时,会出现一个非常大的缺点:控件需要特殊处理并表示不需要的依赖项。

您应该只将这些对象的实际“数据”传递给ViewModel:对于使用InkPresenter的示例,它将是O.k.在我看来,发送ViewModel的StylusPoints而不是InkPresenter本身。更好的是代表StylusPoints的ViewModel类 - 它们可以通过数据绑定(我不知道这是否可以使用InkPresenter)或通过一些介体(例如使用附加属性)映射到实际的StylusPoints。

对于创作,你也可以使用一些你传递的中介,例如: ViewModels然后创建合适的WPF-Control并将VM设置为其DataContext。

答案 1 :(得分:2)

今天我遇到了一个有趣的案例。我正在构建一个包含FlowDocument s集合的UI。这些项目显示在ListView中,其中一个单元格模板为RichTextBox

我遇到的第一个问题是RTB的Document属性不是依赖属性,因此您无法绑定它。幸运的是,在我做之前,一些勇敢的开发人员遇到了这个问题,并实现了一个RichTextBox子类,Document覆盖了一个依赖属性。

在我实施集合的拖放重新排序之前,一切都很顺利。在这里,我发现为什么 Document不是DP的原因之一。更改集合的顺序实际上并不会改变它们绑定的对象的顺序;移动的项目只是刷新其绑定目标。荣耀的是,如果FlowDocument属于一个RichTextBox,则无法将其分配给另一个FlowDocuments。重新排序这些RichTextBox打破了用户界面,这是一个问题,因为我首先要做这个用户界面的全部原因是重新排序这些项目。

我决定使用的锤子是使FlowDocuments成为我视图模型的属性。这样,当我在集合中移动FontFamily时,拥有它们的RTB随之移动。

就个人而言,我不会透露这个类是否可以单元测试。这不是导致错误答案的原因。

这使得错误的答案是,现在我已将此组件放入我的课程中,它不再是事件路由系统的一部分。如果我更改了应用程序范围FlowDocument样式的RichTextBox,则这些控件永远不会听到它。我也无法绑定任何东西。 (至少不容易。)可能还有其他一些我尚未想过的问题。

我不太确定在我的情况下正确的答案是什么。我认为我可能必须修复我的可绑定FlowDocument,以便它维护两个 Document个对象:通过其Document getter和setter向世界公开的对象,以及控件内部的一个。 (也就是说,当某些东西在对象上设置Document属性时,它会将该值保存在其私有字段中,然后将文档的内容复制到基本{{1}}属性的内容中。)

这是一种非常冗长的说法,“在视图模型中创建WPF对象似乎是一个非常糟糕的想法,因为我正在这样做。”