只有一个数据源需要多个BindingSource组件?

时间:2009-09-09 07:36:29

标签: c# data-binding bindingsource icustomtypedescriptor

根据我之前的问题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;

有没有办法绕过很多这个?

基本上,使用我的组件时我想做的是:

  1. 将我的一个自定义组件放到表单
  2. 删除必要的控件(文本框,日期选择器等)
  3. 将控件的数据绑定分配给我的自定义组件上的相关属性
  4. 如果可能的话,我想避免使用项目数据源,桥组件以及构造函数中的代码。我想避免的一切。

    请注意,我不要求任何人给我代码。欢迎任何指示。

0 个答案:

没有答案