启用应用按钮的事件

时间:2013-02-02 02:44:05

标签: c# winforms events button apply

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

所以我可以浏览每个控件的事件并在那里启用按钮,但我想知道是否有更简单的方法来执行此操作,例如全局事件。

修改 澄清一下:我正在寻找一种方法,我不会对每一个控件做任何事情。这样我可以在以后添加更多控件,而不必关心它们......

2 个答案:

答案 0 :(得分: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是否属于包含其他控件的类型。如果是,则recursively使用System.Windows.Forms.Control.ControlCollection中包含的新control调用AddEvents方法。

if else块的第二部分检查控件c的类型,使其适当cast到正确的类型,从而利用正确的事件。如果我们能够在此时确定我们的控件类型,则先前创建的泛型事件将作为处理程序添加。

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

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

这应该是迭代控件并添加通用事件处理程序所需的全部内容。这段代码来自我创建的实际项目,我测试过它以确保它的功能正常。

编辑:我刚刚使用controlGroupBoxPanel GroupBox内的Panel对此进行了测试位于Form上的if...else...内。这就是利用递归的有用性的地方。只要你正确设置了GroupBox块,就不需要知道嵌套的深度。它将尽可能深入,无需使用嵌套循环并知道确切的深度。

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

EDIT3:正如onemancat在评论中指出的那样,实际检查控件是Panel还是Control等并不是完全必要的,因为所有控件都是如此继承自具有Controls属性的基类Control。您可以通过说if (c.Controls.Count > 0) AddEvents(c.Controls);来检查{{1}}是否包含其他控件,但是,如果想要选择要迭代的容器控件,则需要检查我在我的类型中的类型例。如果没有必要这么细化,检查计数更有意义,从不打扰类型检查或转换。

答案 1 :(得分: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。这种方法的优点是,当您向表单添加新控件时,您(或下一个开发人员)不必记住将更改事件连接到启用的按钮,它将自动发生。