Sie können aussetzen Eigenschaften von INestedObj
für die Bindung, aber die Lösung ist sehr messy.To einige Hintergrundinformationen zu geben, alle WinForms-Steuerelemente, die Datenbindung Verwendung TypeDescriptor
, um zu bestimmen, welche Eigenschaften unterstützen existieren auf den Objekten sie verbindlich . Über TypeDescriptionProvider
und CustomTypeDescriptor
können Sie das Standardverhalten überschreiben und somit Eigenschaften hinzufügen/verbergen. In diesem Fall wird die NestedObj
-Eigenschaft ausgeblendet und durch alle Eigenschaften des geschachtelten Typs ersetzt.
Die Technik, die ich zeigen werde hat 2 (big-ish) Einschränkungen:
- Da Sie mit Schnittstellen (und nicht die konkreten Klassen) arbeiten, müssen Sie den Descriptor benutzerdefinierten Typ hinzufügen bei Laufzeit.
- Der benutzerdefinierte Typdeskriptor muss in der Lage sein, eine konkrete Instanz
IParentObj
zu erstellen, daher muss er eine solche Klasse kennen, die über einen Standardkonstruktor verfügt.
(Bitte der lange Code entschuldigen)
Zuerst müssen Sie einen Weg, um ein PropertyDescriptor
aus der verschachtelten Art der Verpackung, so dass sie von dem Muttertyp zugegriffen werden können:
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
);
}
}
Dann Sie müssen einen benutzerdefinierten Typdeskriptor schreiben, der die Eigenschaften des verschachtelten Typs freilegt:
... an d dann müssen Sie einen Weg, um den Deskriptor des Aussetzens von oben:
public class ParentObjDescriptionProvider : TypeDescriptionProvider {
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
object instance) {
return new ParentObjDescriptor();
}
}
schließlich zur Laufzeit (bevor Sie auf die DataGridView
binden), so müssen die Typbeschreibung Anbieter mit der IParentObj
Schnittstelle zuzuordnen. Sie können dies zur Kompilierzeit nicht tun, weil TypeDescriptionProviderAttribute
nicht auf Schnittstellen platziert werden kann ...
TypeDescriptor.AddProvider(new ParentObjDescriptionProvider(), typeof(IParentObj));
Getestet habe ich diese durch ein DataGridView
zu einem IParentObj[]
Bindung und, und siehe da, es schafft Spalten für Prop1
, Prop2
und NestedObj.Prop3
.
Sie müssen sich fragen, aber ... ist es wirklich die Mühe wert?
Dies ist eine wesentlich elegantere Lösung, aber Sie müssen Dinge wie Änderungsbenachrichtigungen opfern (wenn Ihre Objekte das überhaupt unterstützt haben, weiß ich nicht). Eine letzte Sache, die Sie vielleicht untersuchen möchten, ist die 'ITypedList'-Schnittstelle, die eine Sammlung implementieren kann, um benutzerdefinierte Eigenschaften verfügbar zu machen. Es ist ein wenig weniger flockig als die 'TypeDescriptorProvider' Lösung, die ich bei der Reflektion gepostet habe. –