【问题标题】:Dealing with WPF objects inside ViewModel在 ViewModel 中处理 WPF 对象
【发布时间】:2010-03-05 09:36:10
【问题描述】:

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

问题是;这可以吗,还是在 ViewModel 类中创建 WPF 对象是不好的做法?为什么?如果没问题;处理这些对象是否有任何最佳实践或建议?

【问题讨论】:

    标签: .net wpf mvvm


    【解决方案1】:

    不,在您的 ViewModel 中创建和引用 WPF(Control-)类是“不行的”(引用我谈论的最佳实践 - 说 ViewModel 不是 ViewModel,因为它这样做是错误的)。

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

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

    对于创建,您也可以使用一些调解器,例如通过ViewModels 然后创建合适的 WPF-Control 并将 VM 设置为其 DataContext。

    【讨论】:

    • 感谢您的意见。我同意你的意见。我试图避免在 ViewModel 中使用 WPF 控件,但有时这样做会容易得多。
    • 你会说让 ViewModel 提供......说 GradientBrush 也打破了“规则”吗?
    • 我个人会说这是不同的。画笔可以看作是一个数据对象,从 ViewModel 提供给 View 可能有用且有意义。你怎么看?
    • 嗯——嗯——介于两者之间。我会尽量避免它,并更喜欢使用 DataTemplates,其触发器可能会根据某些属性设置颜色/画笔。否则还有ValueConverters。
    【解决方案2】:

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

    我遇到的第一个问题是 RTB 的 Document 属性不是依赖属性,所以你不能绑定到它。幸运的是,一些勇敢的开发人员在我之前遇到了这个问题,并实现了一个 RichTextBox 子类,并将 Document 重写为依赖属性。

    在我实现集合的拖放重新排序之前,一切都很好。在这里,我发现了 为什么 Document 不是 DP 的原因之一。更改集合的顺序实际上并不会更改它们绑定的对象的顺序;移动的项目只是刷新它们的绑定目标。荣耀归于好,如果FlowDocument 属于一个RichTextBox,你不能将它分配给另一个。重新排序这些FlowDocuments 会破坏 UI,这是一个问题,因为我首先使用此 UI 的全部原因是为了重新排序这些项目。

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

    就我个人而言,我不知道这个类是否是可单元测试的。这不是导致此错误答案的原因。

    导致这个错误答案的原因是,既然我已经将该组件放入我的类中,它就不再是事件路由系统的一部分了。如果我在我的应用程序范围的FlowDocument 样式上更改FontFamily,这些控件永远不会听到它。我也无法将任何东西绑定到他们身上。 (至少不容易。)我可能还没有考虑其他问题。

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

    这是一种非常啰嗦的说法,“现在我正在这样做,在视图模型中创建 WPF 对象似乎是一个非常糟糕的主意。”

    【讨论】:

    • 在 ViewModel 中保存 WPF 对象确实似乎是个坏主意。在我的情况下,我可能最终让它工作 - 现在。但我可以想象,如果我以后需要更改与此相关的内容,我很容易遇到问题。
    猜你喜欢
    • 2011-01-20
    • 2010-12-26
    • 1970-01-01
    • 2013-06-30
    • 2020-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多