将DataSource属性添加到自定义WinForms控件

时间:2008-10-29 00:55:56

标签: c# winforms data-binding

我想在我的自定义winforms控件中添加复杂的数据绑定,因此我可以执行以下操作:

myControl.DisplayMember = "Name";
myControl.ValueMember = "Name";
myControl.DataSource = new List<someObject>();

有谁知道必须实现哪些接口等才能实现这一目标?

我已经查看了它,我找到的只是IBindableComponent,但这似乎是针对简单绑定而不是复杂绑定。

3 个答案:

答案 0 :(得分:3)

根据需要的数据绑定类型,将以下属性之一应用于自定义控件:

(这个问题专门提到了 complex 数据绑定,但是给定的代码示例对我来说就像 lookup 数据绑定一样,因此我将两者都包括在内。)

有关示例实现,请查看.NET Framework source code

  • ComplexBindindPropertiesAttributeDataGridView中的实施
  • LookupBindingPropertiesAttributeListControl中的实施

但是这些实现对我来说看起来非常复杂,因此将现有控件(例如DataGridViewListBoxComboBox)嵌入您自己的自定义控件中可能会更容易,利用其现有的数据绑定实现,而不是自己编写。 (如果需要,您可以使嵌入式控件不可见。)这是Microsoft在以下指南中演示的方法:

在那些指南中,他们创建了一个数据源以将自定义控件绑定到外部数据库,但是看起来您只是在试图将自定义控件绑定到内部集合(例如List<T>)。在这种情况下,下面的改编代码可能对您有用。


在Visual Studio的Windows窗体项目中,添加一个新的UserControl

对于复杂数据绑定,将ComplexBindingPropertiesAttribute应用于自定义控件。向其中添加一个DataGridView控件。添加DataSourceDataMember属性,并将它们挂钩到DataGridView自己的属性中。

// ComplexBindingControl.cs
// Adapted from https://docs.microsoft.com/visualstudio/data-tools/create-a-windows-forms-user-control-that-supports-complex-data-binding

using System.ComponentModel;
using System.Windows.Forms;

namespace BindingDemo
{
    [ComplexBindingProperties("DataSource", "DataMember")]
    public partial class ComplexBindingControl : UserControl
    {
        public ComplexBindingControl()
        {
            InitializeComponent();
        }

        // Use a DataGridView for its complex data binding implementation.

        public object DataSource
        {
            get => dataGridView1.DataSource;
            set => dataGridView1.DataSource = value;
        }

        public string DataMember
        {
            get => dataGridView1.DataMember;
            set => dataGridView1.DataMember = value;
        }
    }
}

对于 lookup 数据绑定,将LookupBindingPropertiesAttribute应用于自定义控件。向其中添加一个ListBoxComboBox控件。添加DataSourceDisplayMemberValueMemberLookupMember属性,并将它们挂接到ListBoxComboBox自己的属性中。 / p>

// LookupBindingControl.cs
// Adapted from https://docs.microsoft.com/visualstudio/data-tools/create-a-windows-forms-user-control-that-supports-lookup-data-binding

using System.ComponentModel;
using System.Windows.Forms;

namespace BindingDemo
{
    [LookupBindingProperties("DataSource", "DisplayMember", "ValueMember", "LookupMember")]
    public partial class LookupBindingControl : UserControl
    {
        public LookupBindingControl()
        {
            InitializeComponent();
        }

        // Use a ListBox or ComboBox for its lookup data binding implementation.

        public object DataSource
        {
            get => listBox1.DataSource;
            set => listBox1.DataSource = value;
        }

        public string DisplayMember
        {
            get => listBox1.DisplayMember;
            set => listBox1.DisplayMember = value;
        }

        public string ValueMember
        {
            get => listBox1.ValueMember;
            set => listBox1.ValueMember = value;
        }

        public string LookupMember
        {
            get => listBox1.SelectedValue.ToString();
            set => listBox1.SelectedValue = value;
        }
    }
}

要对其进行测试,请在Visual Studio中构建项目,然后将自定义控件的实例添加到Form中。创建一些示例数据,并使用其相关属性将其绑定到自定义控件。

// Form1.cs

using System.Collections.Generic;
using System.Windows.Forms;

namespace BindingDemo
{
    public partial class Form1 : Form
    {
        private readonly List<SomeObject> data;

        public Form1()
        {
            InitializeComponent();

            // Prepare some sample data.
            data = new List<SomeObject>
            {
                new SomeObject("Alice"),
                new SomeObject("Bob"),
                new SomeObject("Carol"),
            };

            // Bind the data to your custom control...

            // ...for "complex" data binding:
            complexBindingControl1.DataSource = data;

            // ...for "lookup" data binding:
            lookupBindingControl1.DataSource = data;
            lookupBindingControl1.DisplayMember = "Name";
            lookupBindingControl1.ValueMember = "Name";
        }
    }

    internal class SomeObject
    {
        public SomeObject(string name)
        {
            Name = name;
        }

        public string Name { get; set; }
    }
}

答案 1 :(得分:0)

您的类需要继承DataBoundControl类而不是UserControl。

答案 2 :(得分:0)

要运行Chris Tollefson BindingDemo的非常有用的示例而不会出现问题,请在LookupMember getter周围放置try / catch块,如下所示:

public string LookupMember {
       get {
            try {
                return listBox1.SelectedValue.ToString();
            }
            catch { return null; }
        }
        set => listBox1.SelectedValue = value;
    }