控件属性和FindControl函数C#

控件属性和FindControl函数C#,c#,asp.net,controls,C#,Asp.net,Controls,我正在编写一个日历来显示一些事件。每天都有一个用于上午、下午和晚上事件的按钮,当有事件显示按钮已启用且其颜色已更改时。我在html表格中显示这些按钮,当有人更改显示的月份时,程序必须通过禁用所有按钮并再次将其颜色设置为白色来“清理”按钮。问题是,我能够通过在包含按钮的表上使用FindControl方法来启用它们: string butControl = /* id of the button */ Button block = mainTable.FindControl(butControl)

我正在编写一个日历来显示一些事件。每天都有一个用于上午、下午和晚上事件的按钮,当有事件显示按钮已启用且其颜色已更改时。我在html表格中显示这些按钮,当有人更改显示的月份时,程序必须通过禁用所有按钮并再次将其颜色设置为白色来“清理”按钮。问题是,我能够通过在包含按钮的表上使用FindControl方法来启用它们:

string butControl = /* id of the button */
Button block = mainTable.FindControl(butControl) as Button;
block.BackColor = Color.Gray;
block.Enabled = true;
而且效果很好。在我的清理方法中,我不想调用所有按钮的名称,因为有105个,而是使用了以下方法:

    private void CleanUp()
    {
        foreach (Control c in mainTable.Controls)
        {
            Button bot = c as Button;
            if (bot != null)
            {
                bot.BackColor = Color.White;
                bot.Enabled = false;
            }
        }
    }

但这不会更改任何按钮的颜色或启用属性。我的问题是:表的controls属性中的控件是否与通过FindControl方法可以找到的控件相同?或者在检索控件时我做错了什么

问题不在于迭代控件列表而不是层次结构吗?FindControl使用层次结构。可以按如下方式循环控件:

public IEnumerable<T> EnumerateRecursive<T>(Control root) where T : Control
{
    Stack<Control> st = new Stack<Control>();
    st.Push(root);

    while (st.Count > 0)
    {
        var control = st.Pop();
        if (control is T)
        {
            yield return (T)control;
        }

        foreach (Control child in control.Controls)
        {
            st.Push(child);
        }
    }
}

public void Cleanup() 
{
    foreach (Button bot in EnumerateRecursive<Button>(this.mainTable))
    {
        bot.BackColor = Color.White;
        bot.Enabled = false;
    }
}
public IEnumerable枚举递归(控件根),其中T:Control
{
Stack st=新堆栈();
圣推(根);
而(标准计数>0)
{
var control=st.Pop();
如果(控制为T)
{
收益率(T)控制;
}
foreach(Control.Controls中的控件子级)
{
圣普什(儿童);
}
}
}
公共空间清理()
{
foreach(枚举递归中的按钮bot(this.mainTable))
{
bot.BackColor=Color.White;
bot.Enabled=false;
}
}

您也可以使用递归实现它,但我通常更喜欢堆栈,因为它要快得多。

我假设您使用的是ASP表,因为这肯定不起作用。您可以通过其他方式解决它,但如果使用一些HTML对您来说并不重要,我建议您将其重新构造为如下所示:

<form id="form1" runat="server">
    <asp:Panel ID="mainTable" runat="server">
        <table>
            <tr>
                <td>
                    <asp:Button ID="Button1" runat="server" Text="Button" />
                </td>
            </tr>
        </table>
    </asp:Panel>
</form>

请注意,在asp:面板中仅使用html控件,实际按钮除外。使用ASP,您必须递归地查找子对象

编辑: 说到递归地寻找孩子,Stefan在我写完之前提出了确切的建议并提供了代码,我肯定会推荐他的方法;他显然没有我懒

==================================

Stefan的方法有一个小小的错误,即在不知道类型的情况下不能显式地进行类型转换,如果使用泛型,则不能知道类型,正如他所做的那样。这是一个懒惰的调整,纯粹用于按钮,因为您正在使用它

不要给出此“应答”状态。这是对他人工作的腐败。

public IEnumerable<Button> EnumerateRecursive(Control root)
{
    // Hook everything in Page.Controls
    Stack<Control> st = new Stack<Control>();
    st.Push(root);

    while (st.Count > 0)
    {
        var control = st.Pop();
        if (control is Button)
        {
            yield return (Button)control;
        }

        foreach (Control child in control.Controls)
        {
            st.Push(child);
        }
    }
}

public void Cleanup()
{
    foreach (Button bot in EnumerateRecursive(this.mainTable))
    {
        bot.BackColor = Color.White;
        bot.Enabled = false;
    }
}
public IEnumerable枚举递归(控制根)
{
//钩住页面控件中的所有内容
Stack st=新堆栈();
圣推(根);
而(标准计数>0)
{
var control=st.Pop();
如果(控制按钮处于关闭状态)
{
产量返回(按钮)控制;
}
foreach(Control.Controls中的控件子级)
{
圣普什(儿童);
}
}
}
公共空间清理()
{
foreach(枚举递归中的按钮bot(this.mainTable))
{
bot.BackColor=Color.White;
bot.Enabled=false;
}
}

Visual Studio发出吠声,在返回行中显示“无法将type System.Web.UI.Control转换为T”。。。请原谅,如果这个问题的解决方案是显而易见的,我从来没有写过以类型作为参数的方法谢谢Stefan,Millie在这里帮助了我们,你的答案是解决这个问题的基础。非常感谢你!我真的应该在Visual studio中编辑这些答案,而不是在记事本中编辑:-)已修复。我甚至没有使用记事本lol。只是在浏览器中编辑。在我面前的三台机器中,有两台运行着VS,我选择了一台运行了,然后继续不使用它。我没有意识到向泛型添加约束的能力,所以感谢heaps教我一些东西!没问题;注:大约一个月后,我的网站将提供一个框架,其中包括一个更通用的递归枚举器。这是一个很普通的手术。在我的个人资料中填写URL后,该URL即可用;-)哈哈,还是谢谢你:)。。。实际上mainTable是html,这会是非常错误的吗?抱歉,对于web编程来说有点陌生,因为它是html,不需要
runat=“server”
。这仅适用于ASP:Table之类的ASP控件。然而,问题是该ID甚至可能不会注册到ASP。试着做我所做的,让一个asp:Panel包装一个html表,然后在C#中引用面板的ID。另外,我没有足够的代表向Stefan的响应添加注释,但是如果你不想将他的函数用于其他目的,你可以只使用硬代码类型。我将编辑我的回复以向您展示。非常感谢,我也尝试过硬编码按钮类型,但尝试失败,我猜太新手了:S。。。再次感谢!!!:)我已经确定了我的答案。只需要额外的约束,实际上不需要硬编码!我想如果你把我的答案标记为正确答案,对阅读这些帖子的其他人来说会更好。。。