我有一个UserControl,包含多个字段,我想绑定到BindingSource。我还希望UserControl公开一些BindingSource属性,以便它可以放在Form上并绑定到表单上的BindingSource。是否有捷径可寻?我意识到我可以在其BindSource setter中重新绑定UserControl的所有控件。但这似乎是错误的。是否有一些BindingSource代理可以让我将用户控件中的BindingSource链接到表单中的BindingSource?
答案 0 :(得分:5)
根据你的问题,我很难得到你打算做的事情。因此,我会尽力为您提供有关此事的有趣信息。
首先,让我们考虑一下客户管理软件项目中的以下UserControl。
public partial class CustomerManagementUserControl : UserControl {
public CustomerManagementUserControl() {
InitializeComponent();
_customerBindingSource = new BindingSource();
}
public IList<ICustomer> DataSource {
set {
_customerBindingSource.DataSource = value;
}
}
private BindingSource _customerBindingSource;
}
其次,让我们考虑以下表格,该表格应该是您的客户管理表格。
public partial class CustomerManagementForm : Form {
public CustomerManagementForm() {
InitializeComponent();
_customerUserControl = new CustomerManagementUserControl();
_customerUserControl.Name = @"customerUserControl";
}
private void CustomerManagementForm_Load(object sender, EventArgs e) {
// CustomersFacade is simply a static class providing customer management features and requirements.
// Indeed, the GetCustomers() method shall return an IList<ICustomer>.
// The IList type and typed IList<T> are both intended to be bindable as a DataSource for DataBinding.
_customerUserControl.DataSource = CustomersFacade.GetCustomers();
this.Controls.Add(_customerUserControl);
}
private CustomerManagementUserControl _customerUserControl;
}
如果您希望在“属性”窗口中使用CustomerManagementUserControl.DataSource属性,请考虑在属性定义的基础上添加以下内容。
[System.ComponentModel.DesignTimeVisible(true), System.ComponentModel.DesignerCategory("CustomerUserControl"), System.ComponentModel.Description("Sets the CustomerUserControl DataSource property")]
这是做我想你可能想做的事情的一种方式。另一方面,如果你想做的是通过设置一个不同类型的对象作为UserControl.BindingSource.DataSource属性来获得尽可能最抽象的,那么你将不得不编写一个方法来检测类型传递对象,然后相应地绑定属性。也许你可以去的一个很好的方法就是反思,如果你觉得它很舒服的话。以任何可能的方式,您可以想象使用这种多态性功能,您必须自己编写一个所有可绑定对象必须实现的接口。这样,您将避免使用未知的属性名称,何时将绑定UserControl的控件,您将能够将正确的属性绑定到正确的控件等等。
让我们尝试以下方法:
public interface IEntity {
double Id { get; set; }
string Number { get; set; }
string Firstname { get; set; }
string Surname { get; set; }
long PhoneNumber { get; set; }
}
public interface ICustomer : IEntity {
}
public interface ISupplier : IEntity {
string Term { get; set; }
}
public sealed Customer : ICustomer {
public Customer() {
}
public double Id { get; set; }
public string Number { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
public long PhoneNumber { get; set; }
}
public sealed Supplier : ISupplier {
public Supplier() {
}
public double Id { get; set; }
public string Number { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
public long PhoneNumber { get; set; }
public string Term { get; set; }
}
考虑到上面的代码,您可以使用UserControl的DataSource属性与IEntity绑定,因此您的属性可能是这样的。
[System.ComponentModel.DesignTimeVisible(true), System.ComponentModel.DesignerCategory("CustomerUserControl"), System.ComponentModel.Description("Sets the CustomerUserControl DataSource property")]
public IList<IEntity> DataSource {
set {
_customerBindingSource.DataSource = value;
}
}
也就是说,如果你想进一步推动,你可以公开你的UserControl的控件DataBindings属性,以便在设计时设置它们。考虑到这一点,您将希望将BindingSource公开为公共属性,以便您也可以在设计时将其设置,然后从此BindinSource中选择您的DataMember。
我希望这对您有所帮助或至少为您提供一些进一步搜索的记录。
答案 1 :(得分:1)
如果您想自动执行此操作,您可以在用户控件的load事件中查找父表单中的绑定源或类似的内容......
Dim components As Reflection.FieldInfo = typ.GetField("components", Reflection.BindingFlags.DeclaredOnly Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
Dim lstBindingSources As New List(Of BindingSource)
For Each obj As Object In components.Components
Dim bindSource As BindingSource = TryCast(obj, BindingSource)
If bindSource IsNot Nothing Then
lstBindingSources.Add(bindSource)
End If
Next
If lstBindingSources.Count = 1 Then
MyBindingSource.DataSource = lstBindingSources(0).DataSource
End If
答案 2 :(得分:1)
如果在两个bindingsources上为同一个对象引用分配相同的对象引用,则控件将不会在第二个bindingsource上一致地更新。可能,对上述选择的妥协如下:
VS
设计器设置对控件的绑定。designer.vb
带到代码编辑器中。搜索设计器创建的所有"DataBindings.Add"
行。将它们全部复制到记事本中。打字少,拼写错误少,因为VS
设计师正在创建所有这些文字文字属性名称。
答案 3 :(得分:1)
我知道这是一个迟到的答案;但是,阅读这篇文章的其他人可能会有所帮助。
我对UserControl
的数据绑定控件。我需要在BindingSource
上设置UserControl
才能在设计时绑定控件。 &#34;真实&#34;但是,BindingSource
位于Form
。换句话说,UserControl
上的控件应该就像直接坐在表单上一样(或在表单上的ContainerControl
上)。
这个解决方案背后的想法是观察&#34;真实&#34;的DataSourceChanged
事件。 BindingSource
并在其发生变化时将DataSource
分配给本地BindingSource
。为了找到真实的&#34; BindingSource
我让包含它的Form
(或Control
)实现以下界面:
public interface IDataBound
{
BindingSource BindingSource { get; }
}
我们可以查看控件的ParentChanged
事件,以了解控件何时添加到Form
或ContainerControl
。这里的问题是,此ContainerControl
本身可能尚未添加到Form
(或其他ContainerControl
)。在这种情况下,我们订阅我们在父链中找到的最后一个父项的ParentChanged
事件,并等到最后一个父项被添加,依此类推,直到我们找到Control
或{{1实施Form
。找到IDataBound
后,我们会订阅其IDataBound
的{{1}}事件。
DataSourceChanged