当你想递归枚举一个分层对象,根据一些标准选择一些元素时,有许多技术的例子,如"展平",然后使用Linq进行过滤:如下所示:
但是,当您枚举类似Form的Controls集合或TreeView的Nodes集合时,我一直无法使用这些类型的技术,因为它们似乎需要一个参数(对于扩展方法),这是一个IEnumerable集合:传入SomeForm.Controls不编译.
我发现最有用的是:
哪个为您提供Control.ControlCollection的扩展方法,其中包含IEnumerable结果,然后您可以使用Linq.
我修改了上面的例子来解析TreeView的节点没有问题.
public static IEnumerable<TreeNode> GetNodesRecursively(this TreeNodeCollection nodeCollection)
{
    foreach (TreeNode theNode in nodeCollection)
    {
        yield return theNode;
        if (theNode.Nodes.Count > 0)
        {
            foreach (TreeNode subNode in theNode.Nodes.GetNodesRecursively())
            {
                yield return subNode;
            }
        }
    }
}
这是我现在使用扩展方法编写的代码:
    var theNodes = treeView1.Nodes.GetNodesRecursively();
    var filteredNodes = 
    (
        from n in theNodes
            where n.Text.Contains("1")
                select n
    ).ToList();
而且我认为在传递约束的地方可能会有更优雅的方法.
我想知道是否可以一般性地定义这样的过程,以便:在运行时我可以将集合类型以及实际集合传递给泛型参数,因此代码与是否无关它是TreeNodeCollection或Controls.Collection.
我还有兴趣知道是否有任何其他方式(更便宜?fastser?)比第二个链接(上面)中所示,以获得Linq可用的形式的TreeNodeCollection或Control.ControlCollection.
Leppie关于'在第一个(上图)链接的SO帖子中的SelectMany的评论似乎是一个线索.
我对SelectMany的实验是:好吧,称之为"灾难".:)
感谢任何指针.我已经花了几个小时阅读我发现的那些触及这些区域的SO帖子,然后漫无目的地进入像"y-combinator"这样的exotica.一个"谦卑"的经历,我可能会补充:)
我已经使用LINQ一段时间了(并且喜欢它),但是当我遇到.NET专用集合(DataRowCollection,ControlCollection)时,感觉就像我遇到了一个speedbump.有没有办法将LINQ与这些专用控件一起使用,如果不是,您认为Microsoft会在下一版本的框架中解决这个问题吗?或者我们是否继续迭代这些非LINQ方式,或者将项目从集合中拉出到LINQ-able系列中?
我构建了一个自定义WebControl,它具有以下结构:
<gws:ModalBox ID="ModalBox1" HeaderText="Title" runat="server">
    <Contents>
        <asp:Label ID="KeywordLabel" AssociatedControlID="KeywordTextBox" runat="server">Keyword: </asp:Label><br />
        <asp:TextBox ID="KeywordTextBox" Text="" runat="server" />
    </Contents>
    <Footer>(controls...)</Footer>
</gws:ModalBox>
该控件包含两个ControlCollection属性,'Contents'和'Footer'.从未尝试使用多个控件集合构建控件,但是像这样(简化)解决了它:
[PersistChildren(false), ParseChildren(true)]
public class ModalBox : WebControl
{
    private ControlCollection _contents;
    private ControlCollection _footer;
    public ModalBox()
        : base()
    {
        this._contents = base.CreateControlCollection();
        this._footer = base.CreateControlCollection();
    }
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public ControlCollection Contents { get { return this._contents; } }
    [PersistenceMode(PersistenceMode.InnerProperty)]
    public ControlCollection Footer { get { return this._footer; } }
    protected override void RenderContents(HtmlTextWriter output)
    {
        // Render content controls.
        foreach …我怎么才能得到ControlCollection中的texbox?
我尝试:
public static IEnumerable<TextBox> TextBoxes(this ControlCollection controlCollection)
{
    return (IEnumerable<TextBox>)controlCollection.Cast<Control>().Where(c => c is TextBox);
}
但是我收到以下错误:无法将'WhereEnumerableIterator`1 [System.Web.UI.Control]'类型的对象强制转换为'System.Collections.Generic.IEnumerable`1 [System.Web.UI.WebControls.TextBox] ".
我用C#使用Asp.Net 3.5
目前我正在尝试从递归控件集合(转发器)中提取动态创建的控件(复选框和下拉列表)的集合.这是我正在使用的代码.
private void GetControlList<T>(ControlCollection controlCollection, ref List<T> resultCollection)
{
    foreach (Control control in controlCollection)
    {
        if (control.GetType() == typeof(T))
            resultCollection.Add((T)control);
        if (control.HasControls())
            GetControlList(controlCollection, ref resultCollection);
    }
}
我遇到以下问题:
resultCollection.Add((T)control);
我收到了错误......
Cannot convert type 'System.Web.UI.Control' to 'T'
有任何想法吗?
根据问题,我在表单上有两个面板,一个叫做leftPanel,另一个叫做rightPanel.它们控制我表单上的两列布局.
我还在这些面板中折叠/扩展了组框,我希望迭代每个组以刷新布局,使它们在大小调整更改时互相抢购.
这是我的代码:
    private void RefreshLayout()
    {
        int rollingTopLeft = grpiAddressDetails.Top + grpiAddressDetails.Height + 10;
        int rollingTopRight = grpiBranding.Top + grpiBranding.Height + 10;
        foreach(Control temp in leftPanel.Controls && rightPanel.Controls)
        {
            if (temp is GroupBox)
            {
                if (!(temp.Name.Contains("grpi")))    // Top group boxes have 'i' as the 4th character in their name.
                {
                    if (temp.Parent == leftPanel)
                    {
                        temp.Top = rollingTopLeft;
                        rollingTopLeft += temp.Height + 10;
                    }
                    else if(temp.Parent == rightPanel)
                    {
                        temp.Top = rollingTopRight;
                        rollingTopRight += temp.Height + 10;
                    }
                } …