1

我正在编写一个显示一些事件的日历。每天都有一个用于上午、下午和晚上事件的按钮,当有事件显示该按钮已启用并更改其颜色时。我在 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 方法找到的控件相同?或者我在检索控件时做错了什么?

4

2 回答 2

2

问题不是在迭代控件列表而不是层次结构吗?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;
    }
}

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

于 2013-01-17T06:44:18.990 回答
0

我假设您使用的是 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:Panel 中只使用了 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;
    }
}
于 2013-01-17T06:48:10.220 回答