我想在我的自定义winforms控件中添加复杂的数据绑定,因此我可以执行以下操作:
myControl.DisplayMember = "Name";
myControl.ValueMember = "Name";
myControl.DataSource = new List<someObject>();
有谁知道必须实现哪些接口等才能实现这一目标?
我已经查看了它,我找到的只是IBindableComponent
,但这似乎是针对简单绑定而不是复杂绑定。
答案 0 :(得分:3)
根据需要的数据绑定类型,将以下属性之一应用于自定义控件:
ComplexBindingPropertiesAttribute
LookupBindingPropertiesAttribute
(这个问题专门提到了 complex 数据绑定,但是给定的代码示例对我来说就像 lookup 数据绑定一样,因此我将两者都包括在内。)
有关示例实现,请查看.NET Framework source code:
ComplexBindindPropertiesAttribute
在DataGridView
中的实施LookupBindingPropertiesAttribute
在ListControl
中的实施但是这些实现对我来说看起来非常复杂,因此将现有控件(例如DataGridView
,ListBox
或ComboBox
)嵌入您自己的自定义控件中可能会更容易,利用其现有的数据绑定实现,而不是自己编写。 (如果需要,您可以使嵌入式控件不可见。)这是Microsoft在以下指南中演示的方法:
在那些指南中,他们创建了一个数据源以将自定义控件绑定到外部数据库,但是看起来您只是在试图将自定义控件绑定到内部集合(例如List<T>
)。在这种情况下,下面的改编代码可能对您有用。
在Visual Studio的Windows窗体项目中,添加一个新的UserControl
。
对于复杂数据绑定,将ComplexBindingPropertiesAttribute
应用于自定义控件。向其中添加一个DataGridView
控件。添加DataSource
和DataMember
属性,并将它们挂钩到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
应用于自定义控件。向其中添加一个ListBox
或ComboBox
控件。添加DataSource
,DisplayMember
,ValueMember
和LookupMember
属性,并将它们挂接到ListBox
或ComboBox
自己的属性中。 / 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;
}