根据我之前的问题Make properties available for data binding through some kind of interface in .NET?,我在@Marc Gravell的帮助下管理,通过实现界面ICustomTypeDescriptor我可以为表单设计器提供可能或可能的自定义属性实际上,在相关组件上实际上看不到真正的正常属性。
我管理了这个,但我的实施存在缺陷。我现在遇到的最大问题是,如果我在我的表单上删除一个组件,它有两个这样的自定义属性,然后将两个文本框放到表单上,并使用数据绑定,属性检查器中的数据绑定下拉列表需要一个对象数据source,但是我绑定到控件的每个属性都会在表单上添加另一个BindingSource组件。
让我重新说一下。我将自定义组件放到表单上。它有两个属性,可以通过我的ICustomTypeDescriptor实现获得,但不能作为普通属性显示。
然后我将两个文本框放到表单上。我去其中一个属性检查器为Text属性添加数据绑定,它需要项目中的对象数据源,我添加它。然后,在将文本框上的Text属性绑定到我的自定义组件的第一个属性之后,表单设计器添加了另一个组件,即“customDataBindingBindingSource”,用于桥接两者之间的数据绑定。到目前为止,非常好。
然后,当我以相同的方式为其他文本框设置数据绑定时(除了我现在可以选择我的自定义组件的其他属性),添加了另一个这样的桥,“customDataBindingBindingSource1”。如果我继续切换要绑定的属性,每次都会添加一个这样的桥。
这真的有必要吗?
如果没有,我在ICustomTypeDescriptor实施中做错了什么?当然,这是天真和简单的,远非完整,但我不知道我需要修复什么。有什么指针吗?
这是我的自定义类:
public class CustomDataBinding : Component, ICustomTypeDescriptor, INotifyPropertyChanged
{
private String _Property1;
private String _Property2;
public class MyPropertyDescriptor : PropertyDescriptor
{
private String _Name;
public MyPropertyDescriptor(String name)
: base(name, null)
{
_Name = name;
}
public override bool CanResetValue(object component)
{
return true;
}
public override Type ComponentType
{
get { return typeof(CustomDataBinding); }
}
public override object GetValue(object component)
{
CustomDataBinding source = (CustomDataBinding)component;
switch (_Name)
{
case "Property1":
return source._Property1;
break;
case "Property2":
return source._Property2;
break;
default:
return null;
}
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return typeof(String); }
}
public override void ResetValue(object component)
{
SetValue(component, _Name);
}
public override void SetValue(object component, object value)
{
CustomDataBinding source = (CustomDataBinding)component;
switch (_Name)
{
case "Property1":
source._Property1 = Convert.ToString(value);
Debug.WriteLine("Property1 changed to " + value);
break;
case "Property2":
source._Property2 = Convert.ToString(value);
Debug.WriteLine("Property2 changed to " + value);
break;
default:
return;
}
source.OnPropertyChanged(_Name);
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
public CustomDataBinding()
{
_Property1 = "Property1";
_Property2 = "Property2";
}
#region ICustomTypeDescriptor Members
public AttributeCollection GetAttributes()
{
return new AttributeCollection(null);
}
public string GetClassName()
{
return null;
}
public string GetComponentName()
{
return null;
}
public TypeConverter GetConverter()
{
return null;
}
public EventDescriptor GetDefaultEvent()
{
return null;
}
public PropertyDescriptor GetDefaultProperty()
{
return null;
}
public object GetEditor(Type editorBaseType)
{
return null;
}
public EventDescriptorCollection GetEvents(Attribute[] attributes)
{
return new EventDescriptorCollection(null);
}
public EventDescriptorCollection GetEvents()
{
return new EventDescriptorCollection(null);
}
public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
return new PropertyDescriptorCollection(new PropertyDescriptor[] {
new MyPropertyDescriptor("Property1"),
new MyPropertyDescriptor("Property2") });
}
public PropertyDescriptorCollection GetProperties()
{
return GetProperties(null);
}
public object GetPropertyOwner(PropertyDescriptor pd)
{
return this;
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(String name)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public void SetValues(String p1, String p2)
{
_Property1 = p1;
_Property2 = p2;
OnPropertyChanged("Property1");
OnPropertyChanged("Property2");
}
#endregion
}
另外,我需要在表单构造函数中手动将这些桥连接到我最初删除的组件,如下所示:
customDataBindingBindingSource.DataSource = customDataBinding1;
customDataBindingBindingSource1.DataSource = customDataBinding1;
有没有办法绕过很多这个?
基本上,使用我的组件时我想做的是:
如果可能的话,我想避免使用项目数据源,桥组件以及构造函数中的代码。我想避免的一切。
请注意,我不要求任何人给我代码。欢迎任何指示。