gpt4 book ai didi

winforms - 寻找 DataGridView 控件无法绑定(bind)到分层 (OO) 数据的解决方法

转载 作者:行者123 更新时间:2023-12-04 17:05:01 26 4
gpt4 key购买 nike

看起来 DataGridView 控件只能绑定(bind)到平面数据源(所有属性都是原始类型)。我的数据是分层的。例如:

    interface INestedObj
{
string Prop3 { get; }
}

interface IParentObj
{
public string Prop1 { get; }
public string Prop2 { get; }
public INestedObj NestedObj { get; }
}

鉴于此,如何绑定(bind)到实现 IParentObj 的对象?最终你不得不做这样的事情:
grid.Columns["prop1Col"].DataPropertyName = "Prop1";
grid.Columns["prop2Col"].DataPropertyName = "Prop2";

grid.Columns["prop3Col"].DataPropertyName = "How to display Prop3?";

grid.Columns["prop3Col"].DataPropertyName = "NestedObj.Prop3"; // does not work

我正在寻找建议和/或解决方法。

TIA

最佳答案

您可以从 INestedObj 公开属性用于绑定(bind),但解决方案是非常困惑。为了提供一些背景知识,所有支持数据绑定(bind)的 WinForms 控件都使用 TypeDescriptor以确定它们绑定(bind)到的对象上存在哪些属性。通过TypeDescriptionProviderCustomTypeDescriptor ,您可以覆盖默认行为,从而添加/隐藏属性 - 在这种情况下,隐藏 NestedObj属性并将其替换为嵌套类型上的所有属性。

我要展示的技术有两个(大)警告:

  • 由于您使用的是接口(interface)(而不是具体的类),因此您必须在运行时添加自定义类型描述符。
  • 自定义类型描述符需要能够创建 IParentObj 的具体实例,因此它必须知道这样一个具有默认构造函数的类。

  • (请原谅冗长的代码)

    首先,您需要一种包装 PropertyDescriptor 的方法。从嵌套类型,以便它可以从父类型访问:
    public class InnerPropertyDescriptor : PropertyDescriptor {
    private PropertyDescriptor innerDescriptor;

    public InnerPropertyDescriptor(PropertyDescriptor owner,
    PropertyDescriptor innerDescriptor, Attribute[] attributes)
    : base(owner.Name + "." + innerDescriptor.Name, attributes) {
    this.innerDescriptor = innerDescriptor;
    }
    public override bool CanResetValue(object component) {
    return innerDescriptor.CanResetValue(((IParentObj)component).NestedObj);
    }
    public override Type ComponentType {
    get { return innerDescriptor.ComponentType; }
    }
    public override object GetValue(object component) {
    return innerDescriptor.GetValue(((IParentObj)component).NestedObj);
    }
    public override bool IsReadOnly {
    get { return innerDescriptor.IsReadOnly; }
    }
    public override Type PropertyType {
    get { return innerDescriptor.PropertyType; }
    }
    public override void ResetValue(object component) {
    innerDescriptor.ResetValue(((IParentObj)component).NestedObj);
    }
    public override void SetValue(object component, object value) {
    innerDescriptor.SetValue(((IParentObj)component).NestedObj, value);
    }
    public override bool ShouldSerializeValue(object component) {
    return innerDescriptor.ShouldSerializeValue(
    ((IParentObj)component).NestedObj
    );
    }
    }

    然后你需要编写一个自定义类型描述符来暴露嵌套类型的属性:
    public class ParentObjDescriptor : CustomTypeDescriptor {
    public override PropertyDescriptorCollection GetProperties(
    Attribute[] attributes) {
    PropertyDescriptorCollection properties
    = new PropertyDescriptorCollection(null);

    foreach (PropertyDescriptor outer in TypeDescriptor.GetProperties(
    new ParentObj() /* concrete implementation of IParentObj */,
    attributes, true)) {
    if (outer.PropertyType == typeof(INestedObj)) {
    foreach (PropertyDescriptor inner in TypeDescriptor.GetProperties(
    typeof(INestedObj))) {
    properties.Add(new InnerPropertyDescriptor(outer,
    inner, attributes));
    }
    }
    else {
    properties.Add(outer);
    }
    }

    return properties;
    }
    }

    ...然后您需要一种从上面公开描述符的方法:
    public class ParentObjDescriptionProvider : TypeDescriptionProvider {
    public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
    object instance) {
    return new ParentObjDescriptor();
    }
    }

    最后,在运行时(在绑定(bind)到 DataGridView 之前),您必须将类型描述提供程序与 IParentObj 关联起来。界面。你不能在编译时这样做,因为 TypeDescriptionProviderAttribute不能放在接口(interface)上...
    TypeDescriptor.AddProvider(new ParentObjDescriptionProvider(), typeof(IParentObj));

    我通过绑定(bind) DataGridView 对此进行了测试到 IParentObj[]并且,瞧,它为 Prop1 创建列, Prop2NestedObj.Prop3 .

    但是,您必须问自己……真的值得付出所有努力吗?

    关于winforms - 寻找 DataGridView 控件无法绑定(bind)到分层 (OO) 数据的解决方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4209141/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com