在我们正在开发的程序中,用户数据收集在 UserControls 中,这是使用 BindingSources 绑定到业务实体的数据。
我需要以编程方式在 UserControl 中找到所有 BindingSources。
由于 BindingSource 源未添加到 UserControl 的 Controls 集合中,因此我无法在其中进行搜索。
这可以做到吗?
在我们正在开发的程序中,用户数据收集在 UserControls 中,这是使用 BindingSources 绑定到业务实体的数据。
我需要以编程方式在 UserControl 中找到所有 BindingSources。
由于 BindingSource 源未添加到 UserControl 的 Controls 集合中,因此我无法在其中进行搜索。
这可以做到吗?
BindingSource
是 a Component
,而不是 a ,所以确实在集合Control
中找不到它。Controls
但是,当您使用设计器添加组件时,它会创建一个名为components
type的字段IContainer
并将组件添加到其中。该字段是私有的,因此您只能从声明它的类中访问它(除非您使用反射)。
我认为实现您想要的最简单的方法是GetBindingSources
为所有使用控件添加一个方法:
public IEnumerable<BindingSource> GetBindingSources()
{
return components.Components.OfType<BindingSource>();
}
当然,它只适用于BindingSources
使用设计器创建的,而不适用于您动态创建的(除非您将它们添加到容器中)
最大的问题是为我的方法找到一个可用于所有用户控件的解决方案,并且仍然能够使用 Visual Studio 中的 WinForms 设计器。
因为我不知道在不是从 UserControl 派生的类上使用设计器的任何方式,所以我制作了一个没有任何方法的接口 IBusinessEntityEditorView 和一个采用这种视图的扩展方法,使用反射来查找组件字段我在其中搜索我的 BindingSources:
public interface IBusinessEntityEditorViewBase
{
}
...
public static void EndEditOnBindingSources(this IBusinessEntityEditorViewBase view)
{
UserControl userControl = view as UserControl;
if (userControl == null) return;
FieldInfo fi = userControl.GetType().GetField("components", BindingFlags.NonPublic | BindingFlags.Instance);
if (fi != null)
{
object components = fi.GetValue(userControl);
if (components != null)
{
IContainer container = components as IContainer;
if (container != null)
{
foreach (var bindingSource in container.Components.OfType<BindingSource>())
{
bindingSource.EndEdit();
}
}
}
}
}