【问题标题】:How can WPF Converters be used in an MVVM pattern?WPF 转换器如何在 MVVM 模式中使用?
【发布时间】:2009-06-17 14:42:54
【问题描述】:

假设我有一个绑定到 ViewModel A 的视图,它有一个可观察的集合 Customers

这种 MVVM 模式的一个优点是我还可以将视图绑定到 ViewModel B,它会用不同的数据填充它。

但是如果在我的 View converter Converters 中显示我的客户,例如我有一个“ContractToCustomerConverter”,它接受合同并返回要显示的适当客户。

问题在于转换器存在于 MVVM 模式之外,因此不知道我的 ViewModel 有另一个客户来源。

  • View 有没有办法将 ViewModel 传递给 Converter,以便它参与 MVVM 模式提供的解耦?
  • 有没有办法让我以某种方式在我的 ViewModel 中包含转换器,以便转换器使用 ViewModel 可用的当前依赖项?
  • 或者是转换器只是美化了代码隐藏,因此没有在 MVVM 模式中使用,所以如果您使用 MVVM,那么您只需创建自己的“转换器”(ViewModel 类上的方法)返回要在视图上使用的 Image 对象、Visibility 对象、FlowDocuments 等内容,而不是使用转换器?

(我在看到 MVVM Template Toolkit download 附带的 WPF 演示应用程序中使用转换器后遇到这些问题,解压后请参阅“Messenger 示例”。)

【问题讨论】:

    标签: wpf mvvm


    【解决方案1】:

    我通常在 MVVM 中根本不使用转换器,除了纯 UI 任务(例如 BooleanToVisibilityConverter)。恕我直言,您应该在 ContractViewModel 中声明 CustomerViewModel 类型的 Customer 属性,而不是使用 ContractToCustomerConverter

    【讨论】:

      【解决方案2】:

      this conversation中有一条评论很赞同Kent的立场,根本不用Converts,有意思:

      ViewModel 基本上是一个价值转换器。它需要“原始”数据 并将其转换为易于演示的东西,反之亦然。如果 你曾经发现自己将元素的属性绑定到 ViewModel 的 属性,并且您正在使用值转换器,停止!为什么不创建一个 ViewModel 上公开“格式化”数据的属性,然后删除 完全是价值转换器?

      this conversation:

      我唯一能看到的地方 MVVM 中的值转换器 建筑是跨元素的 绑定。如果我绑定 面板对 IsChecked 的可见性 的复选框,那么我将需要使用 BooleanToVisibilityConverter。

      【讨论】:

        【解决方案3】:

        转换器应该很少与 MVVM 一起使用。事实上,我努力完全不使用它们。 VM 应该完成视图完成工作所需的一切。如果视图需要基于ContractCustomer,则VM 上应该有一个Customer 属性,只要Contract 更改,VM 逻辑就会更新该属性。

        这种 MVVM 模式的一个优点是我还可以将 View 绑定到 ViewModel B,后者会用不同的数据填充它。

        我对这种说法提出异议。根据我的经验,不同的 VM 类型之间不会共享视图,这也不是 MVVM 的目标。

        【讨论】:

        • 好的我明白你关于视图不应该在不同的虚拟机之间共享的观点,但是一个 ViewModel 应该能够被不同的视图共享,因此 MVVM 的可测试性优势,对吧?您应该能够将模拟视图和模拟模型连接到 ViewModel,以确保它从模拟模型接收到的所有数据组合都会生成正确的属性值并暴露给视图。你同意吗?
        【解决方案4】:

        对于那些在视图中有效地说没有“非平凡转换器”的人,您如何处理以下问题?

        假设我有一个气候传感器模型,它表示给定位置的各种仪器(气压计、湿度计、温度计等)的读数时间序列。

        假设我的视图模型从我的模型中公开了一个可观察的传感器集合。

        我有一个包含 WPF 工具包 DataGrid 的视图,该工具包绑定到视图模型,其中 ItemsSource 属性设置为可观察的传感器集合。对于给定的传感器,我如何表示每个仪器的视图?通过显示一个小图形(想想 Edward Tufte sparkline 此处),该图形是通过使用转换器 (TimeSeriesToSparklineConverter) 将时间序列转换为图像源而生成的

        这是我对 MVVM 的看法:模型向视图模型公开数据。 View Model 向 View 公开行为、模型数据和状态。视图的工作是直观地表示模型数据,并为与视图模型状态一致的行为提供接口。

        因此,我不相信迷你图图像会出现在模型中(模型是数据,而不是它的特定视觉表示)。我也不相信迷你图图像会出现在 View Model 中(如果我的 View 想要以不同的方式表示数据,比如一个网格行,只显示该系列的最小值、最大值、平均值、标准偏差等?)。因此,在我看来,视图应该处理将数据转换为所需表示的工作。

        因此,如果我想在命令行界面而不是 WPF GUI 中公开某个视图模型的行为、模型数据和给定状态,我不希望我的模型或视图模型包含图像。这是错的吗?我们有SensorCollectionGUIViewModelSensorCollectionCommandLineViewModel 吗?这对我来说似乎是错误的:我认为视图模型是视图的抽象表示,而不是具体的并且与这些名称所暗示的特定技术相关联。

        这就是我对 MVVM 不断发展的理解。所以对于那些说不要使用转换器的人,你在这里做什么?

        【讨论】:

        • 我看到您描述的问题是这样的:使用值转换器,您将创建一个 ClimateSensorToSparklineGraphConverter,它获取气候传感器的集合并输出图像。对于像创建位图图像这样的事情,您不会使用 DataTemplate 和包含 ViewModel 的 ViewModel 集合来执行此操作,在某些时候您需要 C# 代码来创建图像。当在转换器中您还可以访问时,问题就出现了,例如用户集合,用于确定允许当前用户查看的内容。这会破坏 MVVM,因为 ViewModel 应该有用户注入。
        【解决方案5】:

        多年来我一直在使用 Stackoverflow,这是我发布的第一个答案。

        我认为converters属于MVVM中的View,考虑以下情况:

        App 由 3 个团队开发,webapi 团队、webclient 团队和 UI 团队。 UI 经常更改,因此 webclient 团队(从 webapi 接收数据并将它们放入 viewmodel)不能总是修改 viewmodel 以满足 UI 需求。当 UI 团队有不同版本的设计时,这将变得不可能。所以 UI 团队必须有自己的方式来呈现数据,而解决方案就是 Converters。

        希望这对某人有所帮助。

        【讨论】:

          【解决方案6】:

          我将把我的 2 美分加到这个讨论中。

          我确实在有意义的地方使用转换器。

          说明: 在某些情况下,您需要在 UI 中以更多方式在 Model 中表示 1 个值。我通过 1 类型公开这个值。另一种是类型通过转换器处理。如果要通过 VM 中的 2 个属性公开 1 个值,则需要手动处理更新通知。

          例如,我有一个具有 2 个整数的模型:TotalCountDoneCount。现在我希望这两个值都显示在 TextBlocks 中,另外我想显示完成百分比。

          我使用 DivisionConverter 多转换器解决了这个问题,它需要 2 个前面提到的整数。

          如果我在 VM 中有特殊的 PercentDone,我需要在 DoneCount 更新时更新此属性。

          【讨论】:

          • 您基本上通过声明转换器来更新 PercentDone 属性,并在您的绑定引发 propertychanged 时触发它,只有它由具有函数的类表示,而不是属性...所以我不'认为这不是一个真正的好用例。我认为纯粹的 UI 到 UI 的东西需要转换器。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-05-03
          • 1970-01-01
          • 2011-03-29
          • 1970-01-01
          • 1970-01-01
          • 2016-07-12
          • 2023-03-17
          相关资源
          最近更新 更多