1

前の質問のとおり、.NET のある種のインターフェイスを介したデータ バインディングでプロパティを使用できるようにしますか? 、 @Marc Gravellの助けを借りて、インターフェースICustomTypeDescriptorを実装することで、問題のコンポーネントに実際の通常のプロパティとして表示される場合と表示されない場合があるカスタム プロパティをフォーム デザイナーに提供できるようになりました。

私はこれを管理しましたが、私の実装には欠陥があります。私が現在抱えている最大の問題は、そのようなカスタム プロパティが 2 つあるフォームにコンポーネントをドロップし、フォームに 2 つのテキスト ボックスをドロップしてデータ バインディングを使用すると、プロパティ インスペクターのデータ バインディング ドロップダウンにオブジェクト データが必要になることです。ソースですが、コントロールにバインドする各プロパティは、別のBindingSourceコンポーネントをフォームに追加します。

言い換えてみましょう。カスタム コンポーネントをフォームにドロップします。これには 2 つのプロパティがあり、ICustomTypeDescriptorの実装を通じて使用できますが、通常のプロパティとしては表示されません。

次に、2 つのテキストボックスをフォームにドロップします。それらの 1 つのプロパティ インスペクターに移動して、Text プロパティのデータ バインディングを追加します。プロジェクトにオブジェクト データ ソースが必要なので、それを追加します。次に、テキスト ボックスの Text プロパティをカスタム コンポーネントの最初のプロパティにバインドした後、フォーム デザイナーは別のコンポーネント「customDataBindingBindingSource」を追加し、2 つの間のデータ バインディングを橋渡しします。ここまでは順調ですね。

次に、同じ方法で他のテキスト ボックスのデータ バインディングを設定すると (カスタム コンポーネントの他のプロパティを選択できるようになったことを除いて)、別のブリッジ "customDataBindingBindingSource1" が追加されます。バインドするプロパティを切り替え続けると、そのたびにそのようなブリッジが 1 つ追加されます。

これは本当に必要ですか?

そうでない場合、 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. カスタム コンポーネントの 1 つをフォームにドロップする
  2. 必要なコントロール (テキスト ボックス、日付ピッカーなど) をドロップします。
  3. コントロールのデータ バインディングをカスタム コンポーネントの関連するプロパティに割り当てる

可能であれば、プロジェクト データ ソース、ブリッジ コンポーネント、およびコンストラクター内のコードは避けたいと思います。避けたいことすべて。

誰かにコードを教えてほしいと頼んでいるわけではないことに注意してください。どんなポインタでも大歓迎です。

4

0 に答える 0