我在通用DataGrids中显示Business Object,我想通过自定义属性设置列标题,例如:
class TestBo
{
[Header("NoDisp")]
public int ID {get; set;}
[Header("Object's name")]
public String Name { get; set; }
}
到目前为止,这么好,但我还想通过继承将我的显示与我的数据分开:
class TestBO
{
public int ID {get; set;}
public String Name { get; set; }
}
class TestPresentationBO : TestBO
{
//Question: how to simply set the Header attribute on the different properties?
}
我通过Child构造函数中的SetCustomAttribute通过反射看到了一个解决方案,但是它会很麻烦,所以这个问题有一个简单而优雅的技巧吗?
请阻止我破坏数据/演示文稿分离; o)
答案 0 :(得分:6)
问题:如何在不同属性上设置Header属性?
无法按照建议的方式在继承的成员上设置属性,因为属性特定于某个类型。 SetCustomAttribute对你没有帮助 - 当你在运行时构造新类型时,它才有用。一旦编译了属性,就无法在运行时更改它,因为它是元数据的一部分。
如果你想保持分离,你必须找到另一种方式。
(你可以将属性设置为虚拟,在Presentation类中覆盖它们并在覆盖上添加属性,但这看起来很狡猾,并没有真正区分任何东西 - 你最终会在TestPresentationBO中找到一个完整的TestBO类。 。)
答案 1 :(得分:3)
将TestBo
中的属性设为虚拟,并在TestPresentationBO
中覆盖它们。这样你可以添加属性。
答案 2 :(得分:2)
你可以像WCF RIA服务那样做。向TestBO添加属性,如[Presentation]将类型作为参数。这种新类型将重新定义属性,但具有表示属性。 在运行时,您必须获取新类型的标识并获取其属性的自定义属性。
或者忘记属性并使用字典映射BO和演示BO类。此演示文稿BO类与上面的内容相同,即使用自定义属性重新定义属性。
演示文稿BO类从未实例化,只是反映在获取演示文稿信息上。
答案 3 :(得分:2)
想一想,你不能用部分类和MetadatatypeAttribute解决这个问题吗? MVC2使用此模式进行模型验证。
答案 4 :(得分:2)
您使用的是MVVM(模型视图视图模型)模式吗?在我看来,部分来自其他答案,你不能用你想要的自定义属性真正做到这一点。但是,在我看来,TestPresentationBO
实际上就像TestBO
的“视图模型”一样。视图模型基本上是业务或逻辑类的一种包装或代理 - 这基本上是您想要的。 (这个视图模型的摘要可能不是100%准确;我刚刚开始使用MVVM。)
您可以创建TestBOViewModel
来包装TestBO
,然后将TestBOViewModel
的集合传递给数据网格。当然,您可以使用[Header("Object's name")]
等装饰公开包装类的属性。这不使用继承,但我不明白为什么在这种情况下需要使用继承。但是,使用视图模型,可以使用包装器(视图模型)将您的演示文稿(视图)与数据(模型)完全分开。
有关MVVM模式的更多信息,我发现这是一个有趣的读物:WPF Apps With The Model-View-ViewModel Design Pattern。
像这样的东西。当然,您也可以在这里添加验证和其他好东西。
public class TestBOViewModel // extend from DependencyObject
{ // if you want to use dependency properties
private TestBO _myBO;
public TestBOViewModel(TestBO bo)
{
_myBO = bo;
}
[Header("NoDisp")]
public int ID
{
get { return _myBO.ID; }
set { _myBO.ID = value; }
}
}
答案 5 :(得分:0)
对于C#6.0,您可以轻松隐藏继承的成员并引入自己的属性。但是,这可能会隐藏原始属性的任何属性。此简化语法也使该属性成为只读属性,因此您可能需要自行管道get / set。
public class User
{
public string Login { get; set; }
}
public class UserDetail : User
{
[Display(Name = "Login:")]
public new string Login => base.Login;
}