【问题标题】:When the user clicks a button, I want all other buttons to be disabled当用户单击一个按钮时,我希望禁用所有其他按钮
【发布时间】:2009-10-29 15:13:37
【问题描述】:

我有一个 winforms 应用程序,主(也是唯一的)表单有几个按钮。当用户单击一个按钮时,我希望禁用所有其他按钮。

我知道我可以通过在所有按钮上将“启用”设置为 false 来实现这一目标,但在该按钮的单击事件处理程序中已单击的按钮除外,但这是一种漫长而乏味的方法。

我得到了表单上的控件集合,但这不包括我拥有的几个按钮:

        System.Windows.Forms.Control.ControlCollection ctrls = this.Controls;

如何以可维护的方式实现此功能?

谢谢

【问题讨论】:

  • 所以你想禁用除被点击的按钮之外的所有按钮,但又不想遍历它们并一一禁用?

标签: c# winforms


【解决方案1】:
DisableControls(Control c)
{
    c.Enable  = false;
    foreach(Control child in c.Controls)
       DisableControls(child)
}

【讨论】:

  • 小心,这将禁用所有内容,而不仅仅是按钮!
  • 只是对csharpdev的一点补充,你可以添加诸如( if c is Textbox )之类的检查,例如对不同的控件做不同的事情。
【解决方案2】:
private void Form1_Load(object sender, EventArgs e)
{
    foreach (Control ctrl in this.Controls)
    {
        if (ctrl is Button)
        {
            Button btn = (Button)ctrl;
            btn.Click += ButtonClick;
        }
    }

}

private void ButtonClick(object sender, EventArgs e)
{
    foreach (Control ctrl in this.Controls)
    {
        if (ctrl is Button)
        {
            Button btn = (Button)ctrl;
            if (btn != (Button)sender)
            {
                btn.Enabled = false;
            }
        }
    }
}

【讨论】:

    【解决方案3】:

    您可以使用数据绑定,因此您只需在启动时迭代一次:

    public partial class Form1 : Form
    {
        public bool ButtonsEnabled { get; set; }
    
        public Form1()
        {
            InitializeComponent();
    
            // Enable by default
            ButtonsEnabled = true;
    
            // Set the bindings.
            FindButtons(this);
        }
    
        private void button_Click(object sender, EventArgs e)
        {
            // Set the bound property
            ButtonsEnabled = false;
    
            // Force the buttons to update themselves
            this.BindingContext[this].ResumeBinding();
    
            // Renable the clicked button
            Button thisButton = sender as Button;
            thisButton.Enabled = true;
        }
    
        private void FindButtons(Control control)
        {
            // If the control is a button, bind the Enabled property to ButtonsEnabled
            if (control is Button)
            {
                control.DataBindings.Add("Enabled", this, "ButtonsEnabled");
            }
    
            // Check it's children
            foreach(Control child in control.Controls)
            {
                FindButtons(child);
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      扩展 Alex Reitbort 的回答,这是我 20 分钟前刚刚为我正在做的这个项目写的一个示例方法:

          private void Foo(bool enabled)
          {
              foreach (Control c in this.Controls)
                  if (c is Button && c.Tag != null)
                      c.Enabled = enabled;
          }
      

      这个函数不是像他的那样是递归的。但是,因为我知道除了我的表单之外的容器中没有按钮,所以我不需要担心这一点。如果有 子控件(例如 GroupBox 中的控件),我可能会将该代码修改为类似这样;

          private void ToggleControls()
          {
                   Foo(this.Controls, false) // this being the form, of course.
          }
      
          private void Foo(Control.ControlCollection controls, bool enabled)
          {
              foreach (Control c in controls)
              {
                  if (c is Button && c.Tag != null)
                      c.Enabled = enabled;
                  if (c.HasChildren)
                      Foo(c.Controls, enabled);
              }
          }
      

      实际上我更喜欢他的方法,这种递归风格看起来比我想象的要干净一些。只是向您展示另一种方式。

      注意;我的表单上有 6 个按钮,我只希望其中 4 个通过此方法修改其 Enabled 属性。为此,我将它们的 Tag 属性设置为一些随机字符串。这就是我在 if 语句中检查 c.Tag 的原因。如果您知道要禁用每个控件,则可以将其删除。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-02
        • 2022-12-20
        • 2016-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-01
        相关资源
        最近更新 更多