2012-02-24 73 views
1

我有一個模型實現ICustomTypeDescriptor。這是因爲我希望能夠添加不在對象中的自定義屬性並將它們綁定到文本框。奇怪的部分是綁定對PropertyGrid很好,但對文本框不起作用。ICustomTypeDescriptor數據綁定到文本框

此代碼:

DynamicClass<ExtensionModel> binder = new DynamicClass<ExtensionModel>(ext); 
propertyGrid1.SelectedObject = binder; 

,但不是他的一個:

var binder = new DynamicClass<ExtensionModel>(ext); 
_versionLabel.DataBindings.Add("Text", binder, "SelectedVersion", false, DataSourceUpdateMode.OnPropertyChanged); 

在這種情況下,我得到的對象不匹配目標類型。例外。如果我把ext而不是綁定在綁定它工作正常。

是否存在文本框綁定功能的問題?

我對DynamicClass代碼:

public class DynamicClass<T> : ICustomTypeDescriptor 
{ 
    private readonly T _object; 

    public DynamicClass(T trackedObject) 
    { 
     _object = trackedObject; 
    } 

    // Collection to code add dynamic properties 
    public KeyedCollection<string, DynamicProperty> Properties { get; private set; } 

    // ICustomTypeDescriptor implementation 
    AttributeCollection ICustomTypeDescriptor.GetAttributes() 
    { 
     return TypeDescriptor.GetAttributes(_object, true); 
    } 

    string ICustomTypeDescriptor.GetClassName() 
    { 
     return TypeDescriptor.GetClassName(_object, true); 
    } 

    string ICustomTypeDescriptor.GetComponentName() 
    { 
     return TypeDescriptor.GetComponentName(_object, true); 
    } 

    TypeConverter ICustomTypeDescriptor.GetConverter() 
    { 
     return TypeDescriptor.GetConverter(_object, true); 
    } 

    EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() 
    { 
     return TypeDescriptor.GetDefaultEvent(_object, true); 
    } 

    PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() 
    { 
     return TypeDescriptor.GetDefaultProperty(_object, true); 
    } 

    object ICustomTypeDescriptor.GetEditor(Type editorBaseType) 
    { 
     return TypeDescriptor.GetEditor(_object, editorBaseType, true); 
    } 

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents() 
    { 
     return TypeDescriptor.GetEvents(_object, true); 
    } 

    EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes) 
    { 
     return TypeDescriptor.GetEvents(_object, attributes, true); 
    } 

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() 
    { 
     return TypeDescriptor.GetProperties(_object, true); 
    } 

    PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes) 
    { 
     return TypeDescriptor.GetProperties(_object, attributes, true); 
    } 

    object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) 
    { 
     return _object; 
    } 
} 
+0

我們可以看到您的任何自定義描述符嗎? (特別是對於SelectedVersion)通常這應該工作正常(我做了很多瘋狂的自定義描述符的東西),所以我的直覺說:代碼中的錯誤你也沒有顯示 – 2012-02-24 09:37:14

+0

也提到「文本框」,但你似乎綁定到ComboBox ...? – 2012-02-24 09:38:36

+0

我現在將添加代碼。對不起,錯誤的複製/粘貼與綁定:( – 2012-02-24 09:42:40

回答

1

這裏有一個基本的問題,你是給出來的實際對象(ExtensionModel)描述符,但組合框只知道的包裝器(DynamicClass<T>),所以會嘗試調用錯誤對象上的方法。你可以通過將描述符封裝在爲你交換對象的東西上來避免這種情況;如:

class IndirectDescriptor : PropertyDescriptorDecorator 
{ 
    private readonly object instance; 
    public IndirectDescriptor(PropertyDescriptor tail, object instance) : base(tail) 
    { 
     this.instance = instance; 
    } 
    protected override object GetComponent(object component) 
    { 
     return instance; 
    } 
} 

abstract class PropertyDescriptorDecorator : PropertyDescriptor 
{ 
    private readonly PropertyDescriptor tail; 
    static Attribute[] GetAttributes(AttributeCollection attribs) 
    { 
     var arr = new Attribute[attribs.Count]; 
     attribs.CopyTo(arr, 0); 
     return arr; 
    } 
    public PropertyDescriptorDecorator(PropertyDescriptor tail) : base(tail.Name, GetAttributes(tail.Attributes)) 
    { 
     this.tail = tail; 
    } 
    protected virtual object GetComponent(object component) 
    { 
     return component; 
    } 
    public override void AddValueChanged(object component, EventHandler handler) 
    { 
     tail.AddValueChanged(GetComponent(component), handler); 
    } 
    public override void RemoveValueChanged(object component, EventHandler handler) 
    { 
     tail.RemoveValueChanged(GetComponent(component), handler); 
    } 
    public override bool CanResetValue(object component) 
    { 
     return tail.CanResetValue(GetComponent(component)); 
    } 
    public override TypeConverter Converter 
    { 
     get { return tail.Converter; } 
    } 
    public override string Category 
    { 
     get { return tail.Category; } 
    } 
    public override Type ComponentType 
    { 
     get { return tail.ComponentType; } 
    } 
    public override string Description 
    { 
     get { return tail.Description; } 
    } 
    public override bool DesignTimeOnly 
    { 
     get { return tail.DesignTimeOnly; } 
    } 
    public override AttributeCollection Attributes 
    { 
     get { return tail.Attributes; } 
    } 
    public override string DisplayName 
    { 
     get { return tail.DisplayName; } 
    } 
    public override PropertyDescriptorCollection GetChildProperties(object instance, Attribute[] filter) 
    { 
     return tail.GetChildProperties(GetComponent(instance), filter); 
    } 
    public override object GetEditor(Type editorBaseType) 
    { 
     return tail.GetEditor(editorBaseType); 
    } 
    public override object GetValue(object component) 
    { 
     return tail.GetValue(GetComponent(component)); 
    } 
    public override void SetValue(object component, object value) 
    { 
     tail.SetValue(GetComponent(component), value); 
    } 
    public override bool IsBrowsable 
    { 
     get { return tail.IsBrowsable; } 
    } 
    public override bool IsLocalizable 
    { 
     get { return tail.IsLocalizable; } 
    } 
    public override bool IsReadOnly 
    { 
     get { return tail.IsReadOnly; } 
    } 
    public override string Name 
    { 
     get { return tail.Name; } 
    } 
    public override Type PropertyType 
    { 
     get { return tail.PropertyType; } 
    } 
    public override void ResetValue(object component) 
    { 
     tail.ResetValue(GetComponent(component)); 
    } 
    public override bool SupportsChangeEvents 
    { 
     get { return tail.SupportsChangeEvents; } 
    } 
    public override bool ShouldSerializeValue(object component) 
    { 
     return tail.ShouldSerializeValue(GetComponent(component)); 
    } 
}