Damien Flury
Damien Flury

Reputation: 778

WinForms: Get a certain button from its variablename

I'm programming a calculator with C# Windows Forms. I want to listen to the number keys and perform a Button.PerformClick() on the Button which has the same number in its variable name. My buttons are named after the pattern: btn1, btn2, btn3, etc. My code:

            switch (c) //c is the KeyChar Value of the pressed Key
            {
                case '1':
                    {
                        btn1.PerformClick();
                        break;
                    }
                case '2':
                    {
                        btn2.PerformClick();
                        break;
                    }
                case '3':
                    {
                        btn3.PerformClick();
                        break;
                    }

                ...

                case '9':
                    {
                        btn3.PerformClick();
                        break;
                    }

            }

Is there something better code-wise, than just copying everything again and again 9 times? I've tried following (didn't work):

foreach(Button btn in this.Controls){
    if(btn.Text == c.ToString)  //c is the KeyChar value
    {
        btn.PerformClick();
    }
}

Am I doing something wrong or are there any better/smoother ways of doing this, or do I have to do it the way I did?

Upvotes: 2

Views: 576

Answers (4)

dotNET
dotNET

Reputation: 35400

I'd simply set the Tag of each of the 10 buttons to its numeric value and use a single Click event handler for all 10 buttons. Then in the handler routine I'd just read the Tag of sender.

I suggest you do not use keyboard input to perform button clicks. Instead you should direct your keyboard input directly to the operand variable. The same thing should be done by buttons' Click event handler too.

Upvotes: 4

WraithNath
WraithNath

Reputation: 18013

You could use find control each time to get the button, but it would be better performance to add your known buttons to a dictionary of buttons for example. This also would not break if you rename a button and forget to update the code.

eg:

private Dictionary<char, Button> _buttons;

public Form1()
{
    InitializeComponent();

    this.KeyUp += Form1_KeyUp;

    _buttons = new Dictionary<char, Button>();

    _buttons.Add('0', btn0);
    _buttons.Add('1', btn1);
    _buttons.Add('2', btn2);
    //etc
    _buttons.Add('*', btnMultiply);
    _buttons.Add('-', btnMinus);
}

private void Form1_KeyUp(object sender, KeyEventArgs e)
{
    char key = '1'; // Get your key char however you are doing it now

    if (_buttons.ContainsKey(key))
        _buttons[key].PerformClick();
}

Upvotes: 0

C.Evenhuis
C.Evenhuis

Reputation: 26446

Using the Name property isn't wrong, but I personally don't like these secret links between a property and functionality of your application. Instead I would create a Dictionary<char, Button> mapping, and populate it after InitializeComponent().

You can then use:

Button button;
if (mapping.TryGetValue(c, out button))
    button.PerformClick();

Upvotes: 0

Steve
Steve

Reputation: 216273

You can get your button with a single line

 Button b = this.Controls.OfType<Button>()
                .FirstOrDefault(x => x.Name == "btn" + c.ToString());

 if(b != null) 
   b.PerformClick();

This assumes that your buttons are named "btn1", "btn2", etc.. And I am talking about the Name property not the name you gave to the variable that represents your button.

Upvotes: 4

Related Questions