2009-08-04 36 views
2

我有一个从ErrorProvider派生的组件。我有一个BaseFormBaseUserControl,每个都在设计器中添加了这个自定义ErrorProvider。我在BaseForm和其他BaseUserControls上有很多嵌套的BaseUserControls,我需要从顶层窗体或用户控件的嵌套控件中找到所有自定义ErrorProviders以访问特殊功能。如何从控件中获取组件列表?

我该如何浏览所有嵌套控件并找到所有ErrorProvider组件?例如:

List<ErrorProviderEx> customProviders = GetErrorProviders(myUserControl); 

我来最接近的是通过myUserControl.Controls循环和检查每个控件的Control.Container.Components集合递归方法,但是这导致了一些疯狂的逻辑,不必在递归调用在控制的向后看Container。我也试图避免使用反射。

回答

2

FormUserControl的组件未在任何集合中公开。你必须自己做这个。

首先,声明你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 s表示实现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); 

注:一个在.designer.cs文件名为components变量 Windows窗体设计器将所有的组件。你可以选择只在components集合中添加的所有成分的_components名单,但我阅读下列here

[...]我已经意识到 components件实际使用 只当具有 特定构造函数的组件被放置到 表单上时。 [...]如果 组件暴露构造 与特定签名的Public Sub 新(BYVAL c以的IContainer),那么 components成型构件实例化 并传递到组件的 构造

...这就是为什么我在使用components集合时犹豫不决,因为它不一定包含所有组件。但是,它ErrorProvider一起工作。

您可能也想看看this forum post

+0

感谢您的示例。我开始走这条路线,但不想要联结。不过,它看起来可能是最好的选择。我也知道.Desinger.cs文件中的私人组件集合,但不想反映到私人领域。 – 2009-08-04 21:13:31

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