I have 70 buttons whose names are like button1, button2, button3 and so on.
My aim is that whenever button1 is clicked, it will say "1", button2 will say as "2" and so on for the others.
The code for button1 to speak is:
SpeechSynthesizer synthesizer = new SpeechSynthesizer();
private void button1_Click(object sender, EventArgs e)
{
synthesizer.Speak("1");
}
For button2
private void button2_Click(object sender, EventArgs e)
{
synthesizer.Speak("2");
}
and so on for other 68 buttons.
Now it is difficult to implement the 70 button's actions. These button actions follow a pattern - so can anyone suggest a more efficient way I can implement these button handlers to save me writing out 70 different actions?
Try something like this
button1.Tag = "1";
button2.Tag = "2";
...
private void button_Click(object sender, EventArgs e)
{
synthesizer.Speak(((Button)sender).Tag.ToString());
}
Use same handler for all buttons. Sender of event will be the button which raised event. You can get it's name and extract text to say:
private void button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
string text = button.Name.Substring("button".Length);
synthesizer.Speak(text);
}
Create a single handler for all of the buttons.
Cast the sender parameter to get the Button instance that was clicked, and figure out what to do based on its Name, Text, or Tag.
Depending on your UI, you might want to generate all of those buttons in a loop, too.
You can subscribe them to a single eventhandler.
thus:
button1.Click += buttonClicked;
button2.Click += buttonClicked;
// and so on
and the code for the buttonClicked;
private void buttonClicked(object sender, EventArgs e)
{
//This will get the Type first, the name and then the last character on the Name
synthesizer.Speak(sender.GetType().Name.Substring(sender.GetType().Name.Length - 1, 1));
}
this promotes code reuse for you :)
Related
Hey guys first month student here , I need to handle a button event based on which button was clicked before , any simple ideas ? ..(example I've got a listbox with a list of actors and depending on if I click "new actor(first button)" or "modify actor(second button)" I need to either add a new actor or modify the existing actor's stats with the "add button (third button --> needs to know which button was clicked before)".. ??
You can declare a variable of type Button to save the button clicked before.
Note: use Null-conditional operator ?. to avoid potential exception System.NullReferenceException.
Button btn;
private void btnAdd_Click(object sender, EventArgs e)
{
Console.WriteLine(btn?.Name); // print button name
}
private void btnNew_Click(object sender, EventArgs e)
{
btn = btnNew;
}
private void btnModify_Click(object sender, EventArgs e)
{
btn = btnModify;
}
I'm using a Button in a class. When the button is pressed, it should call a routine with the button's corresponding text. How do I convert the sender into a String_Entry? Also, I'm quite a newbie regarding object oriented/class programming, so comments are welcome.
public class String_Entry
{
public TextBox textbox;
public Button send;
// other stuff
public String_Entry()
{
textbox = new TextBox();
send = new Button();
send.Click += new System.EventHandler(this.bSend_Click);
// put in GUI, set parameters and other stuff
}
// other stuff
private void bSend_Click(object sender, EventArgs e)
{
// Trying to get the corresponding String_Entry from the Button click event
Button cntrl = (Button)sender;
String_Entry entry = (String_Entry)(cntrl.Parent);
parse.ProcessHexLine(entry);
}
}
Your solution of encapsulating a button with a textbox and the event handler is sound. It just goes wrong in the event handler:
private void bSend_Click(object sender, EventArgs e)
{
Button cntrl = (Button)sender;
String_Entry entry = (String_Entry)(cntrl.Parent);
parse.ProcessHexLine(entry);
}
Firstly, there is no point to doing anything with sender as it'll be the same as the field send. Next cntrl.Parent will give you a reference to the Form, or other container object, that contains the button, not this instance of String_Entry. To access that, use this. So you can change the event handler to:
private void bSend_Click(object sender, EventArgs e)
{
parse.ProcessHexLine(this);
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btn0_Click(object sender, EventArgs e)
{
MessageBox.Show("called btn 0 click..");
KeyPressEventArgs e0 = new KeyPressEventArgs('0');
textBox1_KeyPress(sender, e0);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
MessageBox.Show("called txtbox_keypress event...");
}
}
Am sorry if this is a silly question,I have just started to learn windows forms, I still find material on the internet confusing.I want to implement calculator. So when number button is pressed it should be filled in textbox. So I thought calling textBox1_keypress() event from button click event would work??? but its not working,
I can manually write the logic in button click event to fill text in text box but if i do so, i have to do the same thing in button1_KeyPress event too. so it would be duplication of code right??...so i thought solution was to call textBox1_KeyPress() event from both button click event and button key press event...but its not working .So what should i do???..is there any other approach which should i follow.
so it would be duplication of code right??
Yes, it would be. So you can do
private void btn0_Click(object sender, EventArgs e)
{
CommonMethod(e);
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
CommonMethod(e);
}
private void CommonMethod(EventArgs e)
{
//Your logic here.
}
The TextBox KeyPress event handler (textBox1_KeyPress) is called after the user presses a key. The KeyPressEventArgs parameter includes information such as what key was pressed. So calling it from your btn0_Click method isn't going to set the text for the TextBox.
Rather, you want to (probably) append whatever number the user pressed to the text already present in the TextBox. Something like
private void btn0_Click(object sender, EventArgs e)
{
textBox1.Text += "0";
}
might be closer to what you're trying to accomplish.
You could put the logic in an extra function like so:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btn0_Click(object sender, EventArgs e)
{
NumberLogic(0),
}
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// I don't know right now if e contains the key pressed. If not replace by the correct argument
NumberLogic(Convert.ToInt32(e));
}
void NumberLogic(int numberPressed){
MessageBox.Show("Button " + numberPressed.ToString() + " pressed.");
}
}
You don't want to tie the events together like that.
A key-press is one thing, handled in one way.
A button click is something totally different and should be handled as such.
The basic reason is this,
The button doesn't know what number it is, you need to tell it that.
A key-press on the other hand, knows what number was pressed.
If you REALLY want to, for some reason, you could use SendKeys to trigger your key-press event in a round-about way, from the button.
SendKeys.SendWait("0");
I can suggest to you to use an Tag Property of the Buttons. Put in it the value of each button in Design mode or in Constructor, create one button event handler for all buttons and use Tag value:
Constructor:
button1.Tag = 1;
button2.Tag = 2;
button1.Click += buttons_Click;
button2.Click += buttons_Click;
Event hadler:
private void buttons_Click(object sender, EventArgs e)
{
textBox1.Text = ((Button)sender).Tag.ToString();
}
I have a label working as a button. I would like when I press a button the click event to this label to take action. for example
private void Label1_Click(object sender, EventArgs e)
{
MessageBox.Show("I pressed this label and showed me this messagebox");
}
Now I want when I press this button, the label1 click event to be performed
private void button1_Click(object sender, EventArgs e)
{
// I want when I press this button something like this happens
Label1.PerformClick();
}
private void button1_Click(object sender, EventArgs e)
{
Label1_Click(sender, e);
}
now if you want to show a message of which control was clicked all in one method do the following
private void label1_Click(object sender, EventArgs e)
{
Control control = (Control)sender;
var name = control.Name;
MessageBox.Show(string.Format("I pressed this {0} and showed me this messagebox",name));
}
Two ways to do this.
First:
private void button1_Click(object sender, EventArgs e)
{
Label1_Click(sender, e); // Just call the Label's click handler
}
Second:
// Bind the Label1_Click handler to the button1 Click event, as they both use the same delegate
button1.Click += new EventHandler(Label1_Click);
With the second approach, note that in C# delegates are multi-cast, so both the button1_Click handler and the Label1_Click handler will be called when the button is clicked, in the order they were bound.
private void button1_Click(object sender, EventArgs e)
{
//What the label click do:
MessageBox.Show("I pressed this label and showed me this messagebox");
}
Is that not easier?
Why do you want to do it ?
I think it would be easier for you to just include the lable click functionality with the button click. Maybe even separate each piece in their own method and call them from the button click. Here is how you'd call another click event.
private void button1_Click(object sender, EventArgs e)
{
label1_Click(sender, e);
}
public class MyLabel:Label
{
public void PerformClick()
{
OnClick(new EventArgs());//InvokeOnClick(this,new EventArgs());
}
}
I have a windows form application which consists of a bunch of controls, but more specifically, two textBoxes. One of them is read only. The read only textBox value is supposed to be the same as the textBox that the user can type into.
So if the user types "Hello World" into textBox A, the value in textBox B should be automatically updated to "Hello World".
How do I go about doing this? I know I just need to set the text values, I'm just not sure where I place the code to get it done automatically rather than executed when a button is click or something along those lines.
TextChanged event:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox2.Text = textBox1.Text;
}
It sounds like you want something like:
writableTextBox.TextChanged += delegate {
readonlyTextBox.Text = writableTextBox.Text;
};
In other words, whenever the text in one textbox changes, update the other. This uses the Control.TextChanged event.
If you want textBoxB to be updated as soon as the text of textBoxA is changed (i.e immediately after the user press a key in textBoxA) the event is TextChanged:
this.textBoxA.TextChanged += new System.EventHandler(this.textBoxA_TextChanged);
private void textBoxA_TextChanged(object sender, EventArgs e)
{
textBoxB.Text = textBoxA.Text;
}
If you prefer to update the text in textBoxB only after the user has finished to edit textBoxA, you should use the Leave event:
this.textBoxA.Leave += new System.EventHandler(this.textBoxA_Leave);
private void textBoxA_Leave(object sender, EventArgs e)
{
textBoxB.Text = textBoxA.Text;
}
This should do what you need:
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox2.Text = textBox1.Text;
}
Even shorter (better?) than the event approach is using winform's databinding. Just use this right after the InitializeComponents call:
readonlyTextBox.DataBindings.Add("Text", writableTextBox, "Text");