Getting access to Button parent - c#

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);
}

Related

How to know which button of button array is clicked

I have array of buttons, which length is variable that User types in. So I made one eventHandler for all buttons. But I have a problem, I need to know which Button is clicked so I can in eventHandler do something that I want. It's more complicated in my code, but I have summarized it. Actually, I just need index of that button that has been clicked.
public Button[] btn;
public void creatingButtons()
{
btn = new Button[x];
for(int i=0; i<btn.Length; i++){
Controls.Add(btn[i]);
btn[i].Click += new EventHandler(btn_Click);
}
}
private void btn_Click(object sender , EventArgs e)
{
int index;
btn[index].Text = "This is clicked button";
}
the Sender is the object what is being clicked so you can use:
private void btn_Click(object sender , EventArgs e)
{
Button clickedBut = sender as Button;
clickedBut.Text = "This is clicked button";
}
By looking at the documentation (found as ~first result by googling "c# button click")
https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.button.-ctor?view=netframework-4.8
public Button[] btns;
public void createButtons(int count) {
btns = new Button[count];
for (int i=0; i<count; i++) {
btns[i] = new Button()
Controls.Add(btns[i]);
btns[i].Click += new EventHandler(btn_Click);
}
}
private void btn_Click(object sender, EventArgs e) {
Button clickedButton = (Button)sender;
int index = Array.IndexOf(btns, clickedButton);
clickedButton.Text = "...button clicked...";
}
Note that you can cast the sender as a Button, and presumably use Array.IndexOf to find the index.
As other answers have pointed out, you can use sender.
But a better solution would be to add a different click handler for the button. If the click handler needs to do different things for each button, or group of buttons then it's technically a different handler. During the creation of the button, you know the purpose of the button, you have the instance of the button, so make the decision then and add an appropriate handler for it.
This way your code is following OOP principles, has good separation of concerns rather than a bunch of adhoc if-statements patched together as an afterthought.

writing one method only for all button's MouseEnter event

I want to show Image on MouseEnter event of button control(I have 6 buttons) ,I can use below code for each button
void button1_MouseEnter(object sender, EventArgs e)
{
this.button1.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.img2));
}
but I Don't want to write it for each buttons enter event ,and hence trying to make it only on method so can use for each button something like this ,but how do I will select different image for different button via this method than ?
void button_MouseLeave(object sender, EventArgs e)
{
var btn = (Button)sender;
this.btn.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.particular image for particular button));
}
You register the same event for all buttons.
For example:
btn1.MouseEnter += genericButton_event;
btn2.MouseEnter += genericButton_event;
You add the image to resources for example using the same name as the button so you can use the btn.Name property. (Something like: btn1.png and btn2.png), and you assign the resource using reflection with the string property "name":
private void genericButton_event(object sender, EventArgs e)
{
var btn = (Button)sender;
btn.BackgroundImage = new Bitmap(System.Reflection.Assembly.GetEntryAssembly().
GetManifestResourceStream("MyProject.Resources" + btn.Name +".png"));
}
You get the bitmap from resources using strings, so you can get the desired background image depending on button name.
You could use the Tag attribute for that. It takes an object - so you can put there whatever you want.
Or you could chose which image to display by naming them after the button and searching for the correctly named image.
Button btn = new Button();
btn.Tag = <YourImage>; // Here you define which image to show
btn.MouseLeave += btn_MouseLeave;
void btn_MouseLeave(object sender, EventArgs e)
{
Button b = (Button)sender;
b.BackGroundImage = (System.Drawing.Image)b.Tag;
}
Of course you'd have to check if the Tag is null.

handling multiple button actions in one action in C#

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 :)

Can't call Click Event on dynamic button

I want to create a method in code behind that creates a button and places it in a PlaceHolder. I want this button to have a Click event.
After calling the "test" method button is placed correctly but the click event is not called.
private void test()
{
Button linkBtn1 = new Button();
linkBtn1.Text = "linkBtn1";
linkBtn1.OnClientClick = "return false;";
linkBtn1.Click += new EventHandler(linkBtn1_Click);
PagesPlaceHolder.Controls.Add(linkBtn1);
}
void linkBtn1_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Removing the OnClientClick = "return false;" is necessary but not sufficient to get this to work. If you want the event handler on the dynamically added button to be triggered, you'll need to add this button every time the page loads.
One simple way would be to save the fact that the button has been added in ViewState, and then check that on PageLoad, and re-add the button if needed.
Here's a sample that works for me (and throws the exception when clicked)
protected void Page_Load(object sender, EventArgs e)
{
//if the button was added previously, add it again
if (ViewState["Added"] != null && (bool)ViewState["Added"])
addButton();
}
//this is the method that adds the button
protected void add_Click(object sender, EventArgs e) {
ViewState["Added"] = true;
addButton();
}
private void addButton() {
Button linkBtn1 = new Button();
linkBtn1.Text = "linkBtn1";
linkBtn1.Click += new EventHandler(linkBtn1_Click);
placeholder1.Controls.Add(linkBtn1);
}
void linkBtn1_Click(object sender, EventArgs e) {
throw new Exception("Button Click Event Triggered. Hello yellow screen!!!");
}
As #oleksii points out, have the clientside code is returning false so the form never gets submitted. You need to comment this out, then your event handler should fire.

Button id as an event handler

I am creating 7 buttons on the fly
when i create the buttons i am trying to have an event handler than can deal with all clicks in one method via a switch. Ideally i want to pass an id with the button that indicates what was clicked, opposed to this solution of
void pdfButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
Console.WriteLine(b.Text);
}
as all of the buttons using this event handler have the same text. I have a unique id associated witht the buttons but no idea how to send them
thanks
You can use the Name or Tag properties.
Put the ID in the Tag property on the button when you create them and then check the ID in your event handler.
Button button = new Button();
button.Tag = 1;
...
void pdfButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
switch ((int)b.Tag)
{
...
}
}
First: Bad practice to handle several clicks in one event via switch. But however a solution would be:
Create your own control which inherits the button and ad your ID as an property. So you can access it via:
MyButton b = (MyButton)sender;
switch(b.ID) {
//Code goes here
}
If each button you add has a unique Id, why not just use the ID property of the button?
Button button = new Button();
button.ID= "Button1";
//...
void pdfButton_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
switch(button.ID)
{
case "Button1":
//...
}
}

Categories