【问题标题】:Add DataSource Property to a Custom WinForms Control将 DataSource 属性添加到自定义 WinForms 控件
【发布时间】:2008-10-29 00:55:55
【问题描述】:

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

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

有谁知道必须实现哪些接口等来实现这一点?

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

【问题讨论】:

  • 您是否曾经在复杂数据绑定源上找到过这个问题的答案?你必须实现的是 bindingcontext 还是 currencymanager ?

标签: c# winforms data-binding


【解决方案1】:

将以下属性之一应用于您的自定义控件,具体取决于您需要哪种数据绑定:

(问题特别提到了 complex 数据绑定,但给定的代码示例对我来说看起来像 lookup 数据绑定,所以我将两者都包括在内。)

例如实现,看.NET Framework source code

  • ComplexBindindPropertiesAttributeDataGridView 中实现
  • LookupBindingPropertiesAttributeListControl 中实现

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

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


在 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 自己的属性中。

// 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;
        }
    }
}

编辑:感谢Frank's answer提醒我listBox1.SelectedValue可能是null。)

要对其进行测试,请在 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; }
    }
}

【讨论】:

  • 我看不到 ComplexBindingProperties 的用途是什么?您的代码在没有该属性的情况下仍然可以运行,是否仅适用于设计器中的某个地方?
【解决方案2】:

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

【讨论】:

  • DataBoundControl 似乎是一个 WebForms 控件。
【解决方案3】:

要顺利运行非常有用的 Chris Tollefson BindingDemo 示例,请在 LookupMember getter 周围放置一个 try/catch 块,如下所示:

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

【讨论】:

    猜你喜欢
    • 2011-06-27
    • 2013-01-09
    • 1970-01-01
    • 2012-07-08
    • 2013-12-13
    • 1970-01-01
    • 2012-10-03
    • 1970-01-01
    • 2011-03-12
    相关资源
    最近更新 更多