我有一个派生自ErrorProvider
的组件。我有一个BaseForm
和BaseUserControl
,每个都在设计器中添加了这个自定义ErrorProvider
。我在BaseUserControls
和其他BaseForm
上有许多嵌套BaseUserControls
,我需要从顶级窗体或用户中找到嵌套控件上的所有自定义ErrorProviders
控制以访问特殊功能。
如何浏览所有嵌套控件并查找所有ErrorProvider
组件?例如:
List<ErrorProviderEx> customProviders = GetErrorProviders(myUserControl);
我最接近的是一个递归方法,循环遍历myUserControl.Controls
并检查每个控件的Control.Container.Components
集合,但这会导致一些疯狂的逻辑,不得不在递归调用中向后看控制的Container
。我也试图避免使用反射。
答案 0 :(得分:2)
Form
或UserControl
的组件未在任何集合中公开。你必须自己做。
首先,声明一个UserControl
将实现的接口:
public interface IComponentList
{
List<Component> Components
{
get;
}
}
接下来,在UserControl
中,将组件添加到构造函数中的列表中,并通过接口属性Components
公开此列表:
public partial class UserControl1 : UserControl, IComponentList
{
private List<Component> _components = new List<Component>();
public UserControl1()
{
InitializeComponent();
_components.Add(errorProvider1);
}
List<Component> IComponentList.Components
{
get
{
return _components;
}
}
}
现在,以下函数应该为您提供实现ErrorProvider
接口的所有UserControl
上IComponentList
的列表:
public List<ErrorProvider> GetErrorProviders(Control myControl)
{
List<ErrorProvider> foundErrorProviders = new List<ErrorProvider>();
GetErrorProviders(myControl, foundErrorProviders);
return foundErrorProviders;
}
protected void GetErrorProviders(Control myControl, List<ErrorProvider> foundErrorProviders)
{
if (foundErrorProviders == null)
{
throw new ArgumentNullException("foundErrorProviders");
}
if (myControl is IComponentList)
{
foreach (Component component in ((IComponentList) myControl).Components)
{
if (component is ErrorProvider)
{
foundErrorProviders.Add((ErrorProvider) component);
}
}
}
foreach (Control control in myControl.Controls)
{
GetErrorProviders(control, foundErrorProviders);
}
}
调用这样的方法:
GetErrorProviders(myUserControl);
注意: Windows窗体设计器将所有组件放在components
文件中名为.designer.cs
的变量中。您可以选择将components
集合中的所有组件添加到_components
列表中,但我会阅读以下here:
[...]我意识到了 实际使用
components
成员 仅当一个组件有一个 具体的构造函数放在一个 形成。 [...]如果 该组件公开了一个构造函数 具有特定签名Public Sub 新的(ByVal c As IContainer),然后components
表单成员已实例化 并传递给组件 构造
...这就是为什么我在使用components
集合时犹豫不决,因为它不一定包含你的所有组件。但将与ErrorProvider
一起使用。
您可能也想查看this forum post。
答案 1 :(得分:0)
我有类似的要求,因为我需要在自定义基本用户控件类派生的UserControls中查找和引用ErrorProvider实例。我在基类中使用了反射来做到这一点。代码如下所示(在VB.NET中)。
Protected ErrorProvidersList As List(Of ErrorProvider) = New List(Of ErrorProvider)()
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
'' Get a collection of error providers that will allow us to check for errors
For Each fi As FieldInfo In Me.[GetType]().GetFields(BindingFlags.NonPublic Or BindingFlags.Instance)
Dim obj As Object = fi.GetValue(Me)
If TypeOf obj Is ErrorProvider Then
ErrorProvidersList.Add(obj)
End If
Next
End Sub