在 UserControl 中使用 BindingSource
我有一个包含多个字段的 UserControl,我希望将其绑定到 BindingSource。 我还希望 UserControl 公开一些 BindingSource 属性,以便可以将其放在表单上并绑定到表单上的 BindingSource。 是否有捷径可寻? 我意识到我可以在其 BindSource setter 中重新绑定 UserControl 的所有控件。 但这似乎是错误的。 是否有一些 BindingSource 代理可以让我将用户控件中的 BindingSource 链接到表单中的 BindingSource?
I have a UserControl with multiple fields that I would like to have bound to a BindingSource. I would also like the UserControl to expose some BindingSource property so that it can be dropped on a Form and be bound to the BindingSource on the form. Is there an easy way to do this? I realize that I can rebind all of the controls of the UserControl in its BindSource setter. But this seems wrong. Is there some BindingSource Proxy that will let me link the BindingSource in the user control to the BindingSource in the form?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
根据你的问题,我很难理解你想要做什么。 因此,我希望我会尽力为您提供有关此事的有趣信息。
首先,让我们考虑客户管理软件项目中的以下 UserControl。
其次,让我们考虑以下表格,它应该是您的客户管理表格。
如果您希望在“属性”窗口中使用 CustomerManagementUserControl.DataSource 属性,请考虑在属性定义的顶部添加以下内容。
这是做我想你可能想做的事情的一种方式。 另一方面,如果您希望通过将不同类型的对象设置为 UserControl.BindingSource.DataSource 属性来获得尽可能最抽象的内容,那么您将必须编写一个可以检测类型的方法传递对象,然后相应地绑定属性。 如果您愿意使用反射,也许您可以采用的一个好方法是使用它。 您可以想象以任何可能的方式使用此类多态性功能,您将必须自己编写一个所有可绑定对象都必须实现的接口。 这样,您将避免未知的属性名称,并且当需要绑定 UserControl 的控件时,您将能够将正确的属性绑定到正确的控件,依此类推。
让我们尝试以下操作:
考虑到上面的代码,您可以使用 UserControl 的 DataSource 属性与 IEntity 绑定,因此您的属性可能像这样。
也就是说,如果您希望更进一步,您可以公开 UserControl 的控件 DataBindings 属性,以便在设计时设置它们。 考虑到这一点,您将希望将 BindingSource 公开为公共属性,以便您也可以在设计时设置它,然后从此 BindinSource 选择您的 DataMember。
我希望这对您有一点帮助,或者至少为您提供一些进一步搜索的线索。
As per your question, I can hardly get what you intend to do. Thus I will try my best to provide you with, I hope, interesting information on that matter.
First, let's consider the following UserControl in a Customer management software project.
Second, let's consider the following Form which should be your Customer management form.
If you're expecting to use CustomerManagementUserControl.DataSource property from within the Property window, please consider adding the following on top of your property definition.
This is one way of doing what I guess you might want to do. On the other hand, if what you wish to do is to get the as most abstract as possible by setting a different type of object as your UserControl.BindingSource.DataSource property, then you will have to write a method which could detect the type of the object passed, then binding the properties accordingly. A nice way you could go, perhaps, is by Reflection, if you're comfortable working with it. In any possible way you may imagine working with such polymorphism features, you will have to write yourself an interface that all of your bindable objects will have to implement. This way, you will avoid unknown property names, and when will come the time to bind your UserControl's controls, you will be able to bind the correct property to the correct control and so forth.
Let's try the following:
Considering the above code, you could use the DataSource property of your UserControl to bind with an IEntity, so your property could like like this.
That said, if you wish to push even further, you could just expose your UserControl's controls DataBindings properties in order to set them on design-time. Considering this, you will want to expose your BindingSource as a public property either so that you may set it on design-time too, then choose your DataMember from this BindinSource.
I hope this helps you both a little or at least, give you some tracks for further searchings.
我知道这是一个迟到的答复; 但是,对于阅读这篇文章的其他人来说可能会有用。
我在
UserControl
上有数据绑定的控件。 我需要在UserControl
上有一个BindingSource
,以便能够在设计时绑定控件。 然而,“真正的”BindingSource
位于Form
上。 换句话说,UserControl
上的控件的行为应该就像它们直接位于表单上(或位于表单上的ContainerControl
上)一样。此解决方案背后的想法是监视“真实”
BindingSource
的DataSourceChanged
事件,并将其DataSource
分配给本地BindingSource
当它改变时。 为了找到“真正的”BindingSource,我让包含它的Form
(或Control
)实现以下接口:我们可以观察控件的
ParentChanged
事件,以便了解何时将其添加到Form
或ContainerControl
。 这里的问题是,此ContainerControl
本身此时可能尚未添加到Form
(或另一个ContainerControl
)中。 在本例中,我们订阅在父级链中找到的最后一个父级的ParentChanged
事件,并等待添加最后一个父级,依此类推,直到找到Control
code> 或Form
实现IDataBound
。 当找到IDataBound
时,我们订阅其BindingSource
的DataSourceChanged
事件。I know it's a late answer; however, it might be useful to someone else reading this post.
I have controls on a
UserControl
that are data-bound. I need to have aBindingSource
on theUserControl
in order to be able to bind the controls at design time. The "real"BindingSource
, however, sits on theForm
. In other words, the controls on theUserControl
should behave as if they were sitting directly on the form (or on aContainerControl
on the form).The idea behind this solution is to watch for the
DataSourceChanged
event of the "real"BindingSource
and to assign itsDataSource
to the localBindingSource
when it changes. In order to find the "real"BindingSource
I let theForm
(orControl
) containing it implement the following interface:We can watch for the
ParentChanged
event of a control in order to know when it has been added to aForm
or aContainerControl
. The problem here is that thisContainerControl
itself might not have been added to theForm
(or anotherContainerControl
) yet at this time. In this case we subscribe to theParentChanged
event of the last parent we find in the parents chain and wait until this last parent has been added, an so on, until we find aControl
orForm
implementingIDataBound
. When aIDataBound
has been found, we subscribe to theDataSourceChanged
event of itsBindingSource
.如果您想自动完成这一切,您可以在用户控件的加载事件或类似的事件中从父表单中查找绑定源...
If you wanted to do this all automatically you could look for the binding source from the parent form in the load event of your user control or something like that...
如果您在两个绑定源上分配与数据源相同的对象引用,则控件将不会在第二个绑定源上一致更新。 可能,对上述选择的折衷方案如下:
VS
设计器设置控件的绑定。designer.vb
。 搜索设计器创建的所有“DataBindings.Add”
行。 将它们全部复制到记事本中。由于
VS
设计器正在创建所有这些文字文本属性名称,因此可以减少打字次数和拼写错误。If you assign the same object reference as the datasource on two bindingsources, the controls will not be updated consistently on the second bindingsource. Possibly, a compromise to the choices above is the following:
VS
designer to set the bindings to the controls.designer.vb
up in the code editor. Search for all the"DataBindings.Add"
lines that were created by the designer. Copy them all to notepad.There is less typing and less typos because the
VS
designer is creating all those literal text property names.此讨论对于发现将登录模型绑定到自定义 UserControl 以在 WinForms 窗口上输入密码的替代方法很有用。 特别有趣的是@Olivier 的帖子实现了 IDataBound 接口。 虽然登录模型的简单性可能有点过分,但我想测试其有效性。 公开一个属性以从自定义密码框返回密码将非常简单明了。 我不知道利用这一财产有多么容易。 正如@WillMarcouiller 评论的那样,可以在password_box 上公开BindingSource 控件。
最后,结果是按照 @DavidWilks 的建议,仅在绑定数据源更改的事件处理程序中包含将 TextBox 与 BindingSource 绑定的步骤。
此示例没有解决表单上 UserControl 的多个实例。 目前,我认为最简单的解决方案是在控件中创建一个属性,以将源名称分配给可以在设计器中处理的源名称。 至少在 VS2022 中,有一个杂项部分接收 UserControl 公开的属性。
This discussion was useful for discovering alternate methods for binding a login model to a custom UserControl for password entry on a WinForms window. Of particular interest was @Olivier's post implementing an IDataBound interface. While probably overkill for the simplicity of a login model, I wanted to test the validity. Exposing a property to return the password from the custom password_box, would be simple and straightforward. What I don't know is how easy it may be to exploit that property. As @WillMarcouiller commented, It is possible to expose a BindingSource control on the password_box.
In the end, the result was to include the step to bind the TextBox with the BindingSource as @DavidWilks suggested, only in the event handler for the Binding DataSource changing.
What this example doesn't address is multiple instances of a UserControl on a form. For now, I'm thinking that the easiest solution would be to create a property in the control to have the source name assigned to which could be handled in the designer. At least in VS2022, there is a miscellaneous section that takes in properties exposed by the UserControl.