对于一个新项目,我最近被要求调查一种方法,将与UI呈现相关的信息附加到WPF应用程序中的业务对象。例如,报告类:
class ExecutionReport
{
[Displayable(Bold, Background=Color.Red)]
public String OrderId{get; private set;}
[Displayable(Normal, HAlignment=Center)]
public String Symbol {get; private set;}
// this should be hidden as it doesn't have DisplayableAttribute
public String ClientOrderId {get; private set;}]
[Displayable(Normal, HAlignment=Right,
Format("If [Position] < 0 then Background=Color.Red"),
Format("If [Position] > 0 then Background=Color.Lime"),
DisplayFormat("+#;-#;0")]
public Int Position {get; private set;}
}
对于我来说,这是一种非常新的方法,因为我在大多数wpf MVVM应用程序中已经对视图和视图模型进行了明确的分离,并且我尽可能地将UI特定的详细信息保留在VM之外。相反,我倾向于使用资源字典和应用于视图层中绑定的简单转换器来编写它。
我的问题是:有没有使用这种实现的wpf / mvvm框架?如果是这样,我很想知道它将如何实现。
有没有明显的陷阱?我想到的第一件事是
更改通知(即INotifyPropertyChanged以触发视图更新)。现在实施这项工作会更加艰难吗?
难以将资源字典用于系统范围的值。例如,也许我想改变整个应用程序中使用的红色。我必须通过ctrl + f来查找业务对象中使用它的每个位置并更改它而不是能够修改单个StaticResource
无法利用DesignTime DataContexts
性能。似乎这需要大量使用反射,这可能不如典型的值转换器那样高效
我很感兴趣,看看我在第二和第三点上是否正确,或者这些事情是否还能实现?
最终我觉得这是一个糟糕的设计,我倾向于编写一个不同的实现来向感兴趣的一方展示我通常会如何解决这类问题。只是想确保我没有遗漏那些显然可能使这更优雅的东西。
答案 0 :(得分:3)
IMO这似乎是一个可怕的想法,它们似乎都是应该作为XAML转换器实现的示例。
所有积分榜似乎都是避免这样做的正当理由。
注意:框架中有一组属性已经提供了一些UI功能(非常有限),请参阅System.ComponentModel.DataAnnotations命名空间。
答案 1 :(得分:1)
这种方法非常流行,它被称为面向方面编程(ASP.NET MVC充分利用它)。最快速写的这个库是PostSharp(参见客户案例研究,有些公司已经将它用于WPF)。 PostSharp中最好的是使用编译时编织。
第一点:
PostSharp得到了经过充分测试的NotifyPropertyChanged
方面,您可以将[NotifyPropertyChanged]
属性添加到类中,并且当值发生更改时,所有属性都会调用PropertyChanged
。
对于第二点:您始终可以使您的属性查找StaticResources
并在属性中传递资源键。
对于第三个(虽然我不是100%肯定)和第四点:编译时编织意味着在编译时将方面“附加”到代码 - 就像你写的那样您附加属性的内部方法/属性。它就像构建后的编译器,不使用反射(如果你写的方面不使用反射),那么性能非常好。
然而在例子中你给了我更喜欢价值转换器和@AwkwardCoder这样的样式 - 但方面(属性)对于“视图”也很有用:例如:它们非常适合验证。
答案 2 :(得分:1)
我同意这似乎是一个可怕的想法,你的评论......
在大多数wpf MVVM应用程序中我已经有一个明确的工作 分离视图和视图模型,我尽可能地努力 保持UI特定的详细信息不在VM中。相反,我会倾斜 使用资源字典和简单的转换器来写这个 应用于视图层中的绑定
......我想总结为什么以及如何避免它。
将您的业务对象直接与实施细节(如颜色,水平对齐或位置)联系起来,似乎是一个短期的胜利(但长期地狱)。