.net 如何解决;“未找到数据成员”;继承绑定源的设计时错误
有时,从向继承者提供绑定源的基窗体或基用户控件继承是有帮助的 例如,继承类可以在设计时将数据源设置为其特定类型或绑定控件,而无需在每个继承控件中编写特殊代码来管理绑定源。您甚至可以通过添加具有数据成员属性集的子绑定源来使用主详细信息 子绑定在运行时可以完美地工作,但不幸的是,设计器在打开保存的子控件时会在设计时遇到此问题。设计器使用反序列化程序来解释文本,而不是实际执行InitializeComponent中的代码。在这种情况下,当子类尝试在基类上查找数据成员时,基类的绑定源尚未设置.net 如何解决;“未找到数据成员”;继承绑定源的设计时错误,.net,winforms,inheritance,windows-forms-designer,bindingsource,.net,Winforms,Inheritance,Windows Forms Designer,Bindingsource,有时,从向继承者提供绑定源的基窗体或基用户控件继承是有帮助的 例如,继承类可以在设计时将数据源设置为其特定类型或绑定控件,而无需在每个继承控件中编写特殊代码来管理绑定源。您甚至可以通过添加具有数据成员属性集的子绑定源来使用主详细信息 子绑定在运行时可以完美地工作,但不幸的是,设计器在打开保存的子控件时会在设计时遇到此问题。设计器使用反序列化程序来解释文本,而不是实际执行InitializeComponent中的代码。在这种情况下,当子类尝试在基类上查找数据成员时,基类的绑定源尚未设置 长话短说:
长话短说:完美的运行时代码,但设计时错误“在数据源上找不到数据成员。”一个解决方案是将BindingSource子类化。生成的类仍然是BindingSource,因此设计器将知道不要在它和绑定控件之间放置额外的绑定源 在设计时,将动态创建设计器希望找到的任何属性描述符。他们不会被记住。设计器将完成初始化并打开,一切都将按预期进行 在运行时,InheritableBindingSource的行为与BindingSource完全相同
public class InheritableBindingSource : BindingSource
{
public override PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
{
if (this.DesignMode)
{
var baseProperties = base.GetItemProperties(listAccessors);
var array = new PropertyDescriptor[baseProperties.Count];
baseProperties.CopyTo(array, 0);
// Return an identical class, but with a modified Find behaviour.
return new DesignerPropertyDescriptorCollection(array);
}
// At runtime, InheritedBindingClass does nothing special.
return base.GetItemProperties(listAccessors);
}
class DesignerPropertyDescriptorCollection : PropertyDescriptorCollection
{
public DesignerPropertyDescriptorCollection(PropertyDescriptor[] properties)
: base(properties, readOnly: true)
{
}
public override PropertyDescriptor Find(string name, bool ignoreCase)
{
// Guaranteed to return a descriptor for any property that is being looked up, whether it has any meaning or not.
return base.Find(name, ignoreCase) ?? new DummyPropertyDescriptor(name);
}
}
// A property descriptor that has no state whatsoever.
class DummyPropertyDescriptor : PropertyDescriptor
{
public DummyPropertyDescriptor(string name)
: base(name, new Attribute[0])
{
}
public override bool CanResetValue(object component)
{
return false;
}
public override Type ComponentType
{
get { return typeof(object); }
}
public override object GetValue(object component)
{
return null;
}
public override bool IsReadOnly
{
get { return false; }
}
public override Type PropertyType
{
get { return typeof(object); }
}
public override void ResetValue(object component)
{
}
public override void SetValue(object component, object value)
{
}
public override bool ShouldSerializeValue(object component)
{
return false;
}
}
}