9

这是一个示例案例来详细说明:

我在我的视图中使用 ItemsControl 动态创建一个简单的条形图,并将项目绑定到我的 BarGraphViewModel 中的 BarViewModels 集合(每个包含百分比值)。每个条应该有不同的颜色。颜色应该从一个集合中选择,例如{Color1, Color2, ..}

集合本身是恒定的,但柱的数量将取决于具体情况。

一个简单的解决方案是创建一个简单的 BarViewModel,如下所示:

public class BarViewModel
{
    public int Percentage { get; set; }

    public SolidColorBrush Stroke { get; private set; }

    public BarGraphViewModel(SolidColorBrush stroke)
    {
        Stroke = stroke;
    }
}

(为简洁起见,我省略了属性更改和验证实现)

现在我可以从我的 BarGraphViewModel 为每个百分比创建一个 BarViewModels 并传入从我的 Color 集合创建的适当的 ColorBrush。

然后在 Xaml 中,我将创建一个简单的 ItemsTemplate 来绑定到这些属性。

只是现在,由于它包含 SolidColorBrush 类型的属性,我的 ViewModel 依赖于 Presentation 框架,如果我想在另一个环境中使用它,则必须对其进行更改。

因此,这是否会破坏 MVVM 最佳实践,或者是否可以接受(您必须在某处划清界限,否则事情会变得太复杂)

我只是想看看其他人对此有何看法,以及是否有其他解决方案可以让 ViewModel 完全不了解表示层而不会变得太复杂。我可以想象 ValueConverters 可以提供帮助吗?

4

3 回答 3

9

In the original Presentation Model pattern described by Martin Fowler, the view "asks" the view-model how to display itself. This seems to favor putting color and size properties on your view-model rather than triggers in your view. The application of this pattern within WPF, however, is somewhat different. In WPF, you typically define how the view looks by using Styles and DataTemplates in the view. Returning specific colors directly from the view-model would be contrary to this approach. So the short answer is: no, don't put color properties on your view-model.

Also within the original Presentation Model pattern, the view-model is an abstraction of the view. So instead of it returning the exact color, it would be preferable to return a "key" that the view can then use to look up the actual color. For example, instead of PersonViewModel.FaceColor returning Red, you'd have PersonViewModel.Mood returning Angry. The view could then use a Style or DataTemplate trigger that translates this to the actual Red color.

So that's my answer and I'm sticking by it, but it's also interesting to consider arguments in the other direction. For one, putting color properties on your view-model is still unit-testable, which seems has become the primary critera for what's okay in the view-model.

Remaining "agnostic" to the view technology isn't a huge factor in either direction. The goal to maintain binary compatibility of view-models with other view technologies is realistic only within the XAML family. Moving all your view-models to their own project which lacks a direct dependency on WPF is a nice idea. But you would have to exclude anything that uses ICommand, or make an exception for a WindowsBase.dll reference. Practically speaking, though, it won't buy you much. We're pretty much glued to Micrsoft technologies! If you decide to port to another GUI framework, then my guess is you're looking at source code conversion. I'm waiting to see if Microsoft goes under before I try it ;) Porting could include changing your color types, if you decided to put them in your view-model. Although not a reason against color properties on your view-model, it's not necessary a reason for it either.

于 2011-11-30T22:50:38.703 回答
8

从理论上讲,您描述的情况违反了 MVVM 中的最佳实践。但是有一个简单的解决方案可以清理您的视图模型。您应该创建自己的类型来表示视图模型中的颜色 - 它可以是字符串、整数或枚举。然后您可以编写自定义 ValueConverter(实现 IValueConverter)来将视图模型颜色类型转换为表示框架相关的颜色表示。转换器应与边界表达式一起使用。转换绑定值的示例在这里

于 2009-12-13T14:30:20.597 回答
2

我看不出您上面的 VM 不好的技术原因,但个人会使用 aBrush而不是特定的子类。我不认为这会破坏 MVVM 最佳实践,因为您的 VM 是您视图的模型。它不一定必须与构建视图的技术无关。

但是,还有其他原因可能是一个坏主意。您的视图模型可能会在非 WPF 环境中使用吗?如果是这样,您将需要一种抽象,然后可以将其转换为特定于平台的构造,WPF 就是Brush这样一个示例。并且不一定需要转换器。您的抽象本身可以是一个视图模型,然后具有特定于平台的子类。例如,您可能有一个Color视图模型,以及一个WpfColor从该视图模型继承的视图模型。

你的团队中有设计师吗?如果是这样,Brush在您的 VM 中使用 a 可能会抑制他们自定义 UI 的能力。您上面的具体情况可能是一个异常值,但一般来说,设计人员和开发人员的协作受益于让 VM 公开状态以及呈现该状态的视图。一旦 VM 决定了任何容量的视觉外观,您就限制了您的设计师可以做出的决定。

根据我的经验,第二个原因是一个更常见的原因,即不在您的 VM 中包含特定于 UI 的结构。

于 2009-12-13T17:54:42.763 回答