When the user clicks a button, I want all other buttons to be disabled
I have a winforms app 开发者_如何学Goand the main (and only) form has several buttons. When the user clicks a button, I want all other buttons to be disabled.
I know I could do this the long way by setting "Enabled" to false on all buttons but the one which has been clicked in the clicked event handler of that button, but this is a long and tedious approach.
I got the collection of controls on the form, but this does not include the several buttons I have:
System.Windows.Forms.Control.ControlCollection ctrls = this.Controls;
How can I go about implementing this functionality in a mantainable fashion?
Thanks
DisableControls(Control c)
{
c.Enable = false;
foreach(Control child in c.Controls)
DisableControls(child)
}
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;
}
}
}
}
You could use databinding, so you only iterate once on startup:
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);
}
}
}
Expanding on Alex Reitbort's answer, here's an example method I just wrote 20 minutes ago for this project I'm doing:
private void Foo(bool enabled)
{
foreach (Control c in this.Controls)
if (c is Button && c.Tag != null)
c.Enabled = enabled;
}
This function is not recursive like his is. However, because I know there are no Buttons within a container other than my form so I don't need to worry about that. If there were child controls (ie controls within a GroupBox for example), I'd probably modify that code to be something like this;
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);
}
}
I actually like his method a little more, that style of recursion looks a little cleaner than mine I think. Just showing you an alternate way.
Note; I have 6 buttons on my form and I only want 4 of them to have their Enabled property modified by this method. To accomplish this, I set their Tag property to some random string. That is why I check for c.Tag in my if statements. You can remove that if you know you want to disable every control.
精彩评论