在Windows窗体中迭代所有控件及其相关控件的通用递归方法

问题描述 投票:0回答:3

有没有通用的递归方法可以迭代windows窗体中的所有控件(包括toolstrip及其项目,bingingnavigator及其项目,...)? (其中一些不是从 Control 类继承的)或者至少迭代toolstrip及其项目、bingingnavigator及其项目?

c# winforms controls toolstrip
3个回答
0
投票

您将在这里遇到麻烦,因为

ToolStrip
使用
Items
而不是
Controls
,并且
ToolStripItem
不继承自
Control
ToolStripItem
Control
都继承自
Component
,所以最多你只能得到一个
IEnumerable<Component>

您可以使用以下扩展方法来完成此操作:

public static class ComponentExtensions
{
    public static IEnumerable<Component> GetAllComponents(this Component component)
    {
        IEnumerable<Component> components;
        if (component is ToolStrip) components = ((ToolStrip)component).Items.Cast<Component>();
        else if (component is Control) components = ((Control)component).Controls.Cast<Component>();
        else components = Enumerable.Empty<Component>();    //  figure out what you want to do here
        return components.Concat(components.SelectMany(x => x.GetAllComponents()));
    }
}

在 Windows 窗体上,您可以在

foreach
循环中处理所有这些组件:

foreach (Component component in this.GetAllComponents())
{
    //    Do something with component...
}

不幸的是,您将进行大量手动类型检查和转换。


0
投票

在这种情况下我通常会这样做:

首先定义一个接受 Control 作为参数的委托:

public delegate void DoSomethingWithControl(Control c);

然后实现一个方法,该方法将此委托作为第一个参数,并将递归执行它的控件作为第二个参数。此方法首先执行委托,然后在控件的 Controls 集合上循环以递归调用自身。这是有效的,因为 Controls 是在 Control 中定义的,并为简单控件返回一个空集合,例如:

public void RecursivelyDoOnControls(DoSomethingWithControl aDel, Control aCtrl)
{
    aDel(aCtrl);
    foreach (Control c in aCtrl.Controls)
    {
        RecursivelyDoOnControls(aDel, c);
    }
}

现在您可以将要为每个控件执行的代码放在一个方法中,并通过委托在 Form 上调用它:

private void DoStg(Control c)
{
    // whatever you want
}

RecursivelyDoOnControls(new DoSomethingWithControl(DoStg), yourForm);

编辑:

由于您也在处理 ToolStripItems,因此您可以定义委托来处理通用对象,然后编写递归方法的不同重载。 IE。像这样的东西:

public delegate void DoSomethingWithObject(Object o);

public void RecursivelyDo(DoSomethingWithObject aDel, Control aCtrl)
{
    aDel(aCtrl);
    foreach (Control c in aCtrl.Controls)
    {
        RecursivelyDoOnControls(aDel, c);
    }
}

public void RecursivelyDo(DoSomethingWithObject aDel, ToolStrip anItem)
{
    aDel(anItem);
    foreach (ToolstripItem c in anItem.Items)
    {
        RecursivelyDo(aDel, c);
    }
}

public void RecursivelyDo(DoSomethingWithObject aDel, ToolStripDropDownButton anItem)
{
    aDel(anItem);
    foreach (ToolStripItem c in anItem.DropDownItems)
    {
        RecursivelyDo(aDel, c);
    }
}

//and so on

0
投票

使用 Visual Studio 2022,您可以应用以下代码:

private static void RecursiveControlProcessing(dynamic userControl)
{
    try
    {
        foreach (var item in userControl.Controls)
        {
            if (item.Controls.Count != 0)
                RecursiveControlProcessing(item);
        }
    }
    catch (Exception ex)
    {
       //handle error
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.