Ty może narazić właściwości z INestedObj
do wiązania, ale rozwiązanie jest bardzo messy.To dać jakieś tło, wszystkie WinForms kontrole, które wspierają wykorzystanie Databinding TypeDescriptor
w celu określenia, które właściwości istnieć na obiektach są one wiążące dla . Poprzez TypeDescriptionProvider
i CustomTypeDescriptor
można zastąpić domyślne zachowanie, a tym samym dodać/ukryć właściwości - w tym przypadku ukrywając właściwość NestedObj
i zastępując ją wszystkimi właściwościami typu zagnieżdżonego.
Technika mam zamiar pokazać ma 2 (Big-ish) Ostrzeżenia:
- Ponieważ pracujemy z interfejsami (a nie konkretnych klas), trzeba dodać deskryptora niestandardowego typu w środowisko wykonawcze.
- Deskryptor typu niestandardowego musi być w stanie utworzyć konkretną instancję o numerze
IParentObj
, dlatego musi znać jedną z takich klas, która ma domyślny konstruktor.
(proszę wybaczyć długie code)
Po pierwsze, trzeba sposobu owijania PropertyDescriptor
z zagnieżdżonego typu tak, że może on być dostępny z rodzaju macierzystego:
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
);
}
}
Następnie trzeba napisać deskryptor niestandardowy typ, który eksponuje właściwości z typu zagnieżdżonego:
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;
}
}
... An d musisz sposób odsłaniając deskryptor z góry:
public class ParentObjDescriptionProvider : TypeDescriptionProvider {
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
object instance) {
return new ParentObjDescriptor();
}
}
Wreszcie, w czasie wykonywania (przed wiążą się z DataGridView
), należy skojarzyć z dostawcą Opis Typ z interfejsem IParentObj
. Nie można tego zrobić podczas kompilacji, ponieważ TypeDescriptionProviderAttribute
nie można umieścić na interfejsach ...
TypeDescriptor.AddProvider(new ParentObjDescriptionProvider(), typeof(IParentObj));
testowałem to poprzez wiązanie DataGridView
do IParentObj[]
i niskie i oto tworzy kolumny dla Prop1
, Prop2
i NestedObj.Prop3
.
Musisz zadać sobie pytanie, chociaż ... czy naprawdę jest to warte tego wysiłku?
To jest znacznie bardziej eleganckie rozwiązanie, ale musisz poświęcić takie rzeczy jak powiadomienie o zmianie (jeśli twoje obiekty go wspierają, nie wiem). Ostatnią rzeczą, na którą warto spojrzeć, jest interfejs "ITypedList", który kolekcja może zaimplementować w celu odsłonięcia właściwości niestandardowych. Jest trochę mniej flakey niż rozwiązanie "TypeDescriptorProvider", które napisałem, po refleksji. –