在视图模型中具有 WPF 细节的优点和缺点
我无法决定如何看待这段代码:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
它是我当前项目中视图模型的一部分,正如您可以想象的那样,Brush
将绑定到UI,在一个相当简单直接的对话框中指示其他数据片段的有效性(无效)。
这段代码的支持者说,既然我们使用的是 WPF,我们不妨在视图模型中允许一些简单的 WPF 特定构造。
反对者说这违反了关注点分离,因为它明确规定了应该仅由视图来处理的风格。
请分享您的论点,如果您对上面的代码不满意,请分享您对替代解决方案的想法。 (我对您关于使用 DataTemplate 的看法特别感兴趣)。
是否有可能存在一种可以被视为最佳实践的解决方案?
I'm having trouble deciding what to think about this piece of code:
public SolidColorBrush Brush
{
get { return IsValid ? _validItemBrush : _invalidItemBrush; }
}
It is part of a view model in my current project and as you can imagine, the Brush
will be bound to some text elements in the UI, to indicate (in-)validity of other pieces of data, in an otherwise fairly simple and straightforward dialog.
The proponents of this piece of code say that since we're using WPF, we might as well allow for some simple WPF specific constructs in the view model.
The opponents say that this violates Separation of Concerns, as it clearly dictates style which should be taken care of solely by the view.
Please share your arguments, and if you're not happy with the code above, please share your ideas around alternative solutions. (I'm particularly interested in what you have to say about using DataTemplate
s).
Is it possible that there is one solution that could be considered best practice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
就我个人而言,我会在 XAML 中定义这两个画笔,并让使用它们的控件根据 IsValid 属性切换画笔(在 xaml 中)。使用 DataTriggers 甚至单个 IValueConverter 可以非常轻松地完成此操作 - 转换器可以采用 2 个画笔和一个布尔值,并相当容易地在它们之间进行交换。
这使业务逻辑表示保持中立 - “画笔”非常特定于特定的表示形式,并且是纯粹的视图选择。将其硬编码到 ViewModel 中违反了单一责任原则,并且不是一个干净的关注点分离。
我非常愿意将其保留在视图中,并根据 ViewModel 特定的
IsValid
(绑定)属性进行切换。Personally, I would have the two brushes be defined in XAML, and have the controls that use them switch brushes (in xaml) based on the IsValid property. This could be done very easily with DataTriggers, or even a single IValueConverter - the converter could take 2 brushes and a boolean and swap between them fairly easily.
This keeps the business logic presentation-neutral - a "Brush" is very specific to a specific form of presentation, and a pure View choice. Hard-coding this into the ViewModel violates the single responsibility principle as well as is not a clean separation of concerns.
I would very much keep this in the View, and switch based on the
IsValid
(bound) property that is ViewModel specific.虽然在某些情况下我可能会在视图模型中使用 WPF 构造,但这不是其中之一。原因如下:
改变更难。如果您将画笔定义为资源并在样式中使用它们,则更改应用程序的配色方案只需加载不同的资源字典即可。如果您在视图模型中对颜色值进行硬编码,那么如果您的最终用户需要不同的颜色,则需要更改许多不同的内容。
测试起来比较困难。如果您想编写一个单元测试来检查属性是否返回正确的画笔,则必须在单元测试中创建一个画笔并比较两者的值,因为它是引用类型。
在许多情况下,甚至可能是大多数情况下,它并没有使代码更简单或更易于维护。您很可能已经在使用样式(假设您熟悉样式),因为它们使 WPF 中的几乎所有内容都变得更加容易。将
IsValid
绑定到画笔颜色只需将DataTrigger
添加到样式即可。这是维护此代码的任何人都希望找到它的地方。当然,有时我确实在视图模型中使用 WPF 构造 - 例如,很久以前就不再怀疑视图模型公开
Visibility
类型的属性是否会出现问题。请注意,上述问题均不适用于该情况。While there are circumstances where I might use WPF constructs in the view model, this isn't one of them. Here's why:
It's harder to change. If you define brushes as resources and use them in styles, changing your application's color scheme can simply be a matter of loading a different resource dictionary. If you hard-code color values in your view models, you have a lot of different things to change if it turns out your end users need different colors.
It's harder to test. If you want to write a unit test that checks to see if a property is returning the right brush, you have to create a brush in your unit test and compare the values of the two, since it's a reference type.
In many, maybe even most cases, it doesn't make the code simpler or easier to maintain. You're pretty likely to already be using a style (assuming that you are conversant with styles), since they make just about everything in WPF easier. Binding
IsValid
to brush colors is just a matter of adding aDataTrigger
to a style. Which is where anyone maintaining this code would expect to find it.There are certainly times when I do use WPF constructs in the view model - for instance, long ago stopped wondering if it was problem if a view model exposed a property of type
Visibility
. Note that none of the above concerns apply to that case.在像您这样纯粹出于美观的情况下,我使用触发器或视觉状态管理器来更改颜色。
有时我确实在 ViewModel 中使用颜色,但前提是它是我的软件规范的一部分(例如,显示患者 CO2 的图表的颜色取决于本地化)。在这种情况下,我使用 Color 结构绑定属性,允许视图使用 SolidColorBrush、GradientStop 或任何它想要的颜色。我最初使用 #AARRGGBB 格式的字符串来完全删除 WPF 依赖项,但我经验丰富的同事不喜欢这样。
In cases like yours where it's purely aesthetic I use Triggers or the Visual State Manager to change colors.
Sometimes I do use colors in my ViewModels, but only if its part of my software spec (e.g., the color of the chart displaying a patient's CO2 depends on localization). In that case, I use a Color struct bound property, allowing the View to use the Color for a SolidColorBrush, a GradientStop, or whatever it wants. I initially used a string in #AARRGGBB format to completely remove the WPF dependency but my more seasoned co-workers didn't like that.