2

我的标准 winform 上的应用按钮在加载时被禁用,我想启用它,如果任何其他控件的状态发生更改(复选框、单选框、文本框等)

所以我可以浏览每个控件的事件并在那里启用按钮,但我想知道是否有更简单的方法来做到这一点,比如全局事件。

编辑 澄清:我正在寻找一种方法,我不必对每个控件都做某事。这样我就可以在以后添加更多控件而不必关心它们...

4

2 回答 2

2

根据您的编辑,我已经修改了我的答案以包含您想要的功能。

首先,您需要一个看起来像这样的通用事件处理程序:

void MyHandler(object obj, EventArgs e)
{
    button1.Enabled = true;
}

其中 button1 是您希望启用的按钮。

然后,您将需要一种递归方法,不仅可以遍历您的Form.Controls.,还可以遍历其中包含的任何容器类型控件。我已经处理了一些常见的容器控件以及一些基本的数据输入控件:

void AddEvents(System.Windows.Forms.Control.ControlCollection Controls)
{
    foreach (Control c in Controls)
    {
        if (c is GroupBox)
        {
            AddEvents(((GroupBox)c).Controls);
        }
        else if (c is Panel)
        {
            AddEvents(((Panel)c).Controls);
        }
        //Expand this series of if...else... to include any 
        //other type of container control
        else if (c is TextBox)
        {
            ((TextBox)c).TextChanged += new EventHandler(MyHandler);
        }
        else if (c is RichTextBox)
        {
            ((RichTextBox)c).TextChanged += new EventHandler(MyHandler);
        }
        else if (c is CheckBox)
        {
            ((CheckBox)c).CheckedChanged += new EventHandler(MyHandler);
        }
        else if (c is DateTimePicker)
        {
            ((DateTimePicker)c).ValueChanged += new EventHandler(MyHandler);
        }
        //Expand this to include any other type of controls your form 
        //has that you need to add the event to
    }
}

if else块的第一部分检查是否属于control包含其他控件的类型。如果是,则递归调用 AddEvents 方法,其中System.Windows.Forms.Control.ControlCollection包含new control

if else块的第二部分检查控件 c 的类型,以便可以将其适当地转换为正确的类型,从而利用正确的事件。如果此时我们能够确定我们的控件类型,则将之前创建的通用事件添加为处理程序。

最后,您需要调用此方法。最好的两个地方可能是在您的构造函数中或在Form.Load事件中。放置它的最佳位置将取决于您的具体情况。为了简单起见,我选择使用我的构造函数,现在看起来像这样:

public Form1()
{
    InitializeComponent();
    AddEvents(this.Controls);
}

这应该是您迭代控件和添加通用事件处理程序所需的全部内容。这段代码来自我创建的一个实际项目,我已经对其进行了测试以确保它具有正确的功能。

编辑:我也刚刚使用controls inside of a GroupBoxinside of a Panelinside of a GroupBoxinside of aPanel进行了测试Form。这就是利用递归的用处所在。只要您正确设置了if...else...块,您就不需要知道确切的嵌套深度。它将尽可能深入,而无需使用嵌套循环并知道确切的深度。

EDIT2:作为旁注,此方法也可以在更细粒度的级别上使用。假设您有多个GroupBox控件,并且您希望只将事件处理程序添加到“grpBox1”中的控件。您可以调用AddEvents(grpBox1.Controls)而不是,AddEvents(this.Controls)这只会将事件处理程序应用于grpBox1.

EDIT3:正如 onemancat 在评论中指出的那样,实际上并不完全有必要检查控件是 aGroupBox还是 aPanel等,因为所有控件都继承自Control具有Controls属性的基类。您可以简单地检查是否Control包含其他控件,if (c.Controls.Count > 0) AddEvents(c.Controls);但是在想要选择要迭代的容器控件的情况下,有必要像我在示例中那样检查类型。如果没有必要如此细化,那么检查计数并且从不打扰类型检查或强制转换确实更有意义。

于 2013-02-02T03:04:16.863 回答
1

如果这将成为您的应用程序中的一个常见主题,您可以创建一些可重用的代码,递归地检查表单的所有控件,并将事件处理程序连接起来。你可以把它放在 InitiaizeComponent(); 之后。

        // Programmatically wire up all Changed events to enable the button
        foreach (Control ctl in this.Controls)
        {
            if (ctl is CheckBox)
            {
                ((CheckBox)ctl).CheckedChanged += new EventHandler(Button_Enable);
            }
            else if (ctl is RadioButton)
            {
                ((RadioButton)ctl).CheckedChanged += new EventHandler(Button_Enable);
            }
            // Here, wire up all other control types you'd like the button to respond to
        }

然后,在处理程序中,启用按钮:

void Button_Enable(object obj, EventArgs e)
{
    MyButton.Enabled = true;
}

您可以在许多表单上调用此方法来为用户创建一致的 UI。这种方法的优点是当您向表单添加新控件时,您(或下一个开发人员)不必记住将更改事件连接到启用的按钮,它会自动发生。

于 2013-02-02T03:18:27.177 回答