Looking for work for the inability of a DataGridView to bind to hierarchical (OO) data

It would seem that a DataGridView control can only communicate with data sources that are flat (all properties are primitive types). My data is hierarchical. For instance:

    interface INestedObj
{
    string Prop3 { get; }
}

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

Given this, how is attached to an object that implements IParentObj? In the end, you will have to do something like this:

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

I am looking for advice and / or work.

TIA

+5
source share
4 answers

Here is a simple solution that came to me at the end of a long day.

Linq , DataGridView.

var query = from pt in parentObjCollection
  select new {Prop1=pt.Prop1, Prop2=pt.Prop2, NestedObj.Prop3=pt.NestedObj.Prop3};

(NestedObj.Prop3) DataPropertyName, .

, .

+3

INestedObj , messy. , WinForms, , TypeDescriptor, , , . TypeDescriptionProvider CustomTypeDescriptor , , / - NestedObj .

, , 2 (-) :

  • ( ), .
  • 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();
    }
}

, ( , DataGridView), IParentObj. , TypeDescriptionProviderAttribute ...

TypeDescriptor.AddProvider(new ParentObjDescriptionProvider(), typeof(IParentObj));

, DataGridView IParentObj[], low behold - Prop1, Prop2 NestedObj.Prop3.

, ... ?

+7

, "NestedObj.Prop3" . , CellFormatting DataGridView, DataBoundItem Prop3. , CellValidated, DataBoundItem.

, , , .

+2

The easiest way I've found is to create a Self property. See This Solution: Matching a combobox column to a datagridview for each row (not the entire column)

0
source

All Articles