Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从列表中排除控件容器_C#_Linq_Predicate - Fatal编程技术网

C# 从列表中排除控件容器

C# 从列表中排除控件容器,c#,linq,predicate,C#,Linq,Predicate,例如,如果我有一个带有此容器的表单: +---------------------------------panel 1----+ | | | +------------------panel 2---+ | | | | | | | textbox1 |

例如,如果我有一个带有此容器的表单:

+---------------------------------panel 1----+
|                                            |
|   +------------------panel 2---+           |
|   |                            |           |
|   | textbox1                   |           |
|   | combobox1        checkBox1 |           |
|   +----------------------------+           |
|                                            |
|   +------------tableLayoutPanel1-+         |
|   |                              |         |
|   | textbox2                     |         |
|   +------------------------------+         |
|                                            |
|   +-------------FlowLayoutPanel1-+         |
|   |textbox3  Combobox2           |         |
|   +------------------------------+         |
|                                            |
+--------------------------------------------+
我已经有了一个函数,用于从给定容器中获取特定类型的所有控件(通过递归调用获取包含的偶数控件):

公共静态IEnumerable FindAllChildrenByType(此控件)
{
IEnumerable controls=control.controls.Cast();
返回控件
第()类
.Concat(controls.SelectMany(ctrl=>FindAllChildrenByType(ctrl));
}
这可以正常工作(这里返回textbox1、combobox1、checkbox1、textbox2、textbox3、combobox2)

现在,我想要一个具有类似行为的新函数:从容器中获取所有控件,但这些控件不包括在特定类型的容器中。 在我的示例中,该函数可以返回panel1中包含的所有控件,这些控件从未包含在tableLayoutPanel中(此处为textbox1、combobox1、checkbox1、textbox3、combobox2)

我试过:

public static IEnumerable<T> FindAllChildrenByType<T>(this Control control)
    {
        IEnumerable<Control> controls = control.Controls.Cast<Control>();
        return controls
            .OfType<T>()
            .Concat<T>(controls .Where(ctrl => ctrl.GetType() != typeof(TableLayoutPanel))
                                .SelectMany<Control, T>(ctrl => FindAllChildrenByType<T>(ctrl))
                        );
    }
公共静态IEnumerable FindAllChildrenByType(此控件)
{
IEnumerable controls=control.controls.Cast();
返回控件
第()类
.Concat(controls.Where(ctrl=>ctrl.GetType()!=typeof(TableLayoutPanel))
.SelectMany(ctrl=>FindAllChildrenByType(ctrl))
);
}
以及:

公共静态IEnumerable FindAllChildrenByType2(此控件)
{
IEnumerable controls=control.controls.Cast();
返回控件
第()类
.Concat(controls.SelectMany(ctrl=>FindAllChildrenByType(ctrl)))
.Where(ctrl=>ctrl.GetType()!=typeof(TableLayoutPanel));
}
同样的结果是:我得到了所有控件的列表,甚至那些必须被排除的控件(示例中TableLayoutPanel中的textBox2)

知道我在哪里迷路了吗?

基于使用非递归方法遍历树结构,我想出了这个方法:

公共静态IEnumerable GetChildControls(此控件根,
类型excludedContainer=null)
其中TControl:Control
{
var queue=新队列();
queue.Enqueue(root);
while(queue.Any())
{
var next=queue.Dequeue();
如果(!next.GetType().Equals(excludedContainer))
foreach(next.Controls中的控件子级)
{
排队。排队(子级);
}
如果(!next.HasChildren&&next是TControl类型的)
{
收益型;
}
}
}
非递归方法总是首选的,因为它们不会耗尽调用堆栈(尽管在这种情况下,无论如何也不太可能)


它的功能基本上与原来的相同:在
while
循环中逐级收集控件。我只将
堆栈
替换为
队列
,因此控件从上到下返回。当然,还添加了您要查找的条件:筛选类型和排除的容器类型。

您尝试的方法有什么问题?我获得了所有控件,即使是tableLayoutPanel中的控件。我无法重现该问题
.Concat(controls.Where(ctrl=>ctrl.GetType()!=typeof(TableLayoutPanel)).SelectMany(ctrl=>FindAllChildrenByType(ctrl))
似乎根据需要排除textbox2。这叫什么?请看我的例子,事实上,我已经创建了一个例子来说明我的问题,我没有试图用它来执行程序。实际上,我使用带有用户控件的函数来初始化包含控件的某些属性,并且我已经研究了调用返回的枚举,以查看假定忽略的控件是否已添加到列表中。我想虫子藏在别处了,我会更深入地搜索。。。
public static IEnumerable<T> FindAllChildrenByType<T>(this Control control)
    {
        IEnumerable<Control> controls = control.Controls.Cast<Control>();
        return controls
            .OfType<T>()
            .Concat<T>(controls .Where(ctrl => ctrl.GetType() != typeof(TableLayoutPanel))
                                .SelectMany<Control, T>(ctrl => FindAllChildrenByType<T>(ctrl))
                        );
    }
public static IEnumerable<T> FindAllChildrenByType2<T>(this Control control)
    {
        IEnumerable<Control> controls = control.Controls.Cast<Control>();
        return controls
            .OfType<T>()
            .Concat<T>(controls.SelectMany<Control, T>(ctrl => FindAllChildrenByType<T>(ctrl)))
            .Where<T>(ctrl => ctrl.GetType() != typeof(TableLayoutPanel));
    }