Remove Handler to Button - c#

I'm trying to remove a handler (Click) from a button, I tried many ways but they didn't work.
I create two buttons like this:
private void CreateButtons()
{
Button button1 = new Button()
{
Text = "Start"
};
Button button2 = new Button()
{
Text = "Stop"
};
this.Controls.Add(button1);
button1.Click += Button1_Click;
this.Controls.Add(button2);
button2.Click += Button2_Click;
}
The first one just creates a MessageBox:
private void Button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello World");
}
The second one should remove the handler:
private void Button2_Click(object sender, EventArgs e)
{
button1.Click -= Button1_Click;
}
Unfortunately after clicking button2, button1 keeps generating a MessageBox. What am I doing wrong?

It appears that your form has a different button you've created at an earlier time named button1.
Remove that, and make your button1 and button2 fields of the form.
public partial class Form1 : Form
{
private Button button1;
private Button button2;
public Form1()
{
InitializeComponent();
}
private void CreateButtons()
{
button1 = new Button()
{
Font = new Font(Font.FontFamily, 10, FontStyle.Bold),
BackColor = Color.Yellow,
Width = 79,
Height = 62,
Location = new Point(141, 191),
Text = "Start"
};
button2 = new Button()
{
Font = new Font(Font.FontFamily, 10, FontStyle.Bold),
BackColor = Color.Yellow,
Width = 79,
Height = 62,
Location = new Point(338, 191),
Text = "Stop"
};
this.Controls.Add(button1);
button1.Click += Button1_Click;
this.Controls.Add(button2);
button2.Click += Button2_Click;
}
private void Button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello World");
}
private void Button2_Click(object sender, EventArgs e)
{
button1.Click -= Button1_Click;
}
private void Form1_Load(object sender, EventArgs e)
{
CreateButtons();
}
}

Related

How to remove panels from button C#

I have created a function that creates a new panel each time a button is pressed, alongside with a button, which should remove the entire panel when pressed.
Here is my code for creating the panels and the button :
Panel panel;
private void button1_Click(object sender, EventArgs e)
{
panel = new Panel();
panel.BackColor = Color.FromArgb(38, 38, 38);
panel.Margin = new System.Windows.Forms.Padding(10);
flowLayoutPanel1.Controls.Add(panel);
panel.Show();
Button delbutton = new Button();
delbutton.Text = "X";
flowLayoutPanel1.Controls.Add(delbutton);
delbutton.Click += new EventHandler(this.ButtonFunction_Click);
}
Considering that every panel created has this delbutton , how can i remove the panel of which delbutton button was pressed?
I tried to add this method to the button, but it removes panel randomly :
void ButtonFunction_Click (Object sender,EventArgs e)
{
foreach (Control controlObj in flowLayoutPanel1.Controls)
{
flowLayoutPanel1.Controls.Remove(controlObj);
controlObj.Dispose();
}
}
You can add the relevant Panel as a Tag property of its Button, then you can get that in the Click handler
private void button1_Click(object sender, EventArgs e)
{
var panel = new Panel
{
BackColor = Color.FromArgb(38, 38, 38),
Margin = new Padding(10),
};
flowLayoutPanel1.Controls.Add(panel);
panel.Show();
var delbutton = new Button
{
Text = "X",
Tag = panel,
};
delbutton.Click += ButtonFunction_Click;
flowLayoutPanel1.Controls.Add(delbutton);
}
private void ButtonFunction_Click(Object sender, EventArgs e)
{
var button = (Button)sender;
((Control)button.Tag).Dispose();
button.Dispose();
}

A button created inside code doesn't react to it's event

I just started c# and encountered an error.
I use a button AddSquare to add a another button button and then using it I want to change a textbox ObjectName text on that button's click. But nothing happens.
public partial class Form1 : Form
{
const int UseFieldHeight = 580;
const int UseFieldWidth = 830;
const int UseFieldUperCoordinateX = 234;
const int UseFieldUperCoordinateY = 101;
Button button = new Button();
public Form1()
{
InitializeComponent();
}
private void AddSquare_Click(object sender, EventArgs e)
{
button.Size = new Size(50, 50);
button.BackColor = Color.Black;
button.BackgroundImageLayout = ImageLayout.Stretch;
button.Location = new Point(UseFieldUperCoordinateX, UseFieldUperCoordinateY);
button.Anchor = AnchorStyles.Left;
button.Visible = true;
InitializeComponent();
Controls.Add(button);
button.BringToFront();
button.Click += new EventHandler(button_Click);
}
void button_Click(object sender, EventArgs e)
{
ObjectName.Text = "TEST";
}
}
Is there something else I have to do?
I think it would work if you remove the InitializeComponent(); of your AddSquare_Click Event.

How to set mouse hover for ALL buttons?

I have bunch of buttons on my form. And I would like to make it a bit nicer so button changing color and font to bold when mousei s over it seems like good idea. I would appreciate any help
button.BackColor = Color.Cyan;
button.Font = new Font(button.Font.Name, button.Font.Size, FontStyle.Bold);
EDIT:
this is working for me:
private void button1_MouseEnter(object sender, EventArgs e)
{
((Button)sender).BackColor = Color.PaleTurquoise;
((Button)sender).Font = new Font(((Button)sender).Font.Name, ((Button)sender).Font.Size, FontStyle.Bold);
}
private void button1_MouseLeave(object sender, EventArgs e)
{
((Button)sender).BackColor = Color.WhiteSmoke;
((Button)sender).Font = new Font(((Button)sender).Font.Name, ((Button)sender).Font.Size, FontStyle.Regular);
}
(there is button1_mousenter (or mouseleave) set as action for every button
Just select them all in your Form view and go to the mousehover event.
and write your code like this:
private void button_mousehover (object sender, EventArgs e)
{
((Button)sender).BackColor = Color.Cyan;
((Button)sender).Font = new Font(((Button)sender).Font.Name, ((Button)sender).Font.Size, ((Button)sender).FontStyle.Bold;
}
You can add MouseEnter and MouseLeave events to your buttons that changes the buttons' colors.
https://msdn.microsoft.com/en-us/library/system.windows.forms.control.mouseenter(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.forms.control.mouseleave(v=vs.110).aspx
// bind handler to MouseEnter Event
this.yourButton1.MouseEnter += new System.EventHandler(this.allButtons_MouseEnter);
this.yourButton2.MouseEnter += new System.EventHandler(this.allButtons_MouseEnter);
// bind handler to MouseLeave Event
this.yourButton1.MouseLeave += new System.EventHandler(this.allButtons_MouseLeave);
this.yourButton2.MouseLeave += new System.EventHandler(this.allButtons_MouseLeave);
// enter handler
private void allButtons_MouseEnter(object sender, System.EventArgs e)
{
Button btn = (Button)sender;
btn.BackColor = Color.Cyan;
btn.Font = new Font(btn.Font.Name, btn.Font.Size, FontStyle.Bold);
}
// leave handler
private void allButtons_MouseLeave(object sender, System.EventArgs e)
{
Button btn = (Button)sender;
btn.BackColor = Color.DeepPink; // whatever your original color was
btn.Font = new Font(btn.Font.Name, btn.Font.Size, FontStyle.Regular);
}

How to dynamically create buttons and add events to them?

I have array of buttons, and array of labels:
Label[] labels = new Label[10];
Button[] but = new Button[10];
While clicking the other button I want to dynamically create new button and new label from the array, i also want the but[i] to change the tex of labels[i]:
private void button1_Click(object sender, EventArgs e)
{
labels[i] = new Label();
labels[i].Location = new System.Drawing.Point(0, 15+a);
labels[i].Parent = panel1;
labels[i].Text = "Sample text";
labels[i].Size = new System.Drawing.Size(155, 51);
labels[i].BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
a = labels[i].Height + labels[i].Top;
but[i] = new Button();
but[i].Text = "-";
but[i].Location = new System.Drawing.Point(0, labels[i].Height + labels[i].Top);
but[i].Parent = panel1;
but[i].Size = new System.Drawing.Size(155, 10);
but[i].Click += new System.EventHandler(but_Click);
i++;
}
private void but[i]_Click(object sender, EventArgs e)
{
labels[i].Text = "Changed Text";
}
But apparently I can't put an array in an event handler, how should I do it then?
One way to do this is to make your method return a handler instead of being a handler:
private EventHandler but_Click(int i)
{
return (s, e) => labels[i].Text = "Changed Text";
}
And use it like:
but[i].Click += but_Click(i);
Or do it inline:
but[i].Click += (s, ea) => labels[i].Text = "Changed Text";
What's happening in either of these is some compiler magic to capture the i variable. It's equivalent to this (which is also a valid, if verbose, way to do it):
class MyWrapper {
private int i;
public MyWrapper(int i) {
this.i = i;
}
public void TheHandler(object sender, EventArgs e) {
// TODO: capture the object that owns `labels` also, or this won't work.
labels[i].Text = "Changed Text";
}
}
//call with
but[i].Click += new EventHandler(new MyWrapper(i).TheHandler);
You could add the array index to the button as Tag property, and then pull it back out in but_Click.
So, add
but[i].Tag = i;
to the button creation. And then change the event handler:
private void but_Click(object sender, EventArgs e)
{
int buttonIndex = (int)((Button)sender).Tag;
labels[buttonIndex].Text = "Changed Text";
}
Or put the event handler inline:
but[i].Click += (s,e) => { label[i].Text = "Changed Text"; }
Or another option using the Tag property, add:
but[i].Tag = label[i];
...
private void but_Click(object sender, EventArgs e)
{
Label label = (Label)((Button)sender).Tag;
label.Text = "Changed Text";
}
Advantage of this approach is you're not relying on keeping arrays in synch after the initial creation of the controls.
I guess this is self-explaining:
public void SomeMehthod()
{
Button btn1 = new Button();
Button btn2 = new Button();
Button btn3 = new Button();
// Your button-array
Button[] btns = new Button[]
{
btn1,
btn2,
btn3
};
foreach(Button btn in btns)
{
// For each button setup the same method to fire on click
btn.Click += new EventHandler(ButtonClicked);
}
}
private void ButtonClicked(Object sender, EventArgs e)
{
// This will fire on any button from the array
// You can switch on the name, or location or anything else
switch((sender as Button).Name)
{
case "btn1":
// Do something
break;
case "btn2":
// Do something
break;
case "btn3":
// Do something
break;
}
}
Or if your array is accessible globaly:
Button[] btns = new Button[5];
Label[] lbls = new Label[5];
private void ButtonClicked(Object sender, EventArgs e)
{
Button clicked = sender as Button;
int indexOfButton = btns.ToList().IndexOf(clicked);
// ..IndexOf() returns -1 if nothign is found
if(indexOfButton > 0)
{
lbls[indexOfButton].DoWhatYouWant...
}
}

Changing the properties of a dynamically created control

I have a Form with a LayoutPanel that has dynamically added buttons inside. The buttons are added at runtime, which works, but my problem is I'd like to set the properties to one of the buttons to disabled if a textBox is empty and enable it when it the textBox is not empty.
Here is a code example, with the error I am receiving below:
private void Form1_Load(object sender, EventArgs e)
{
// Create 3 buttons
Button button1 = new Button();
button1.Name = "button1";
tableLayoutPanel1.Controls.Add(button1, 0, 0);
Button button2 = new Button();
button1.Name = "button2";
tableLayoutPanel1.Controls.Add(button2, 0, 0);
Button button3 = new Button();
button3.Name = "button1";
tableLayoutPanel1.Controls.Add(button3, 0, 0);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text))
{
button1.Enabled = false;
}
else
{
button1.Enabled = true;
}
}
CS0103 The name 'button1' does not exist in the current context
Should I be declaring the buttons elsewhere so the entire code can see that they do in fact exist or is my problem elsewhere? Thanks.
You must declare a Button outside Form1_Load if you want to access the button with name directly from other methods, because in your case the buttons are just available in the Form1_Load method :
Button button1;
private void Form1_Load(object sender, EventArgs e)
{
// Create 3 buttons
button1 = new Button();
button1.Name = "button1";
tableLayoutPanel1.Controls.Add(button1, 0, 0);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
button1.Enabled = !string.IsNullOrEmpty(textBox1.Text);
}
or if you want declare Buttons inside Form1_Load, you can access to Button like this :
private void textBox1_TextChanged(object sender, EventArgs e)
{
var btn = tableLayoutPanel1.Controls.OfType<Button>().Where(x => x.Name == "button1").FirstOrDefault();
(btn as Button).Enabled = !string.IsNullOrEmpty(textBox1.Text);
}
As an alternative, you could dynamically get the control from the Layout Panel and set the enabled property like this:
private void textBox1_TextChanged(object sender, EventArgs e)
{
Control button = tableLayoutPanel1.Controls["button1"];
button.Enabled = string.IsNullOrEmpty(textBox1.Text) ? false : true;
}
This approach is not as "safe" as declaring the buttons at form level, but I thought it would be useful to mention for times when you need to be genuinely dynamic in referencing controls.
There are a couple ways you can do this, one would be to use the Find method of the TableLayoutPanel's Controls Collection like this.
private void textBox1_TextChanged(object sender, EventArgs e)
{
Button btn =(Button)tableLayoutPanel1.Controls.Find("button1", true)[0];
if (string.IsNullOrEmpty(textBox1.Text))
{
btn.Enabled = false;
}
else
{
btn.Enabled = true;
}
}
The second would be to use the buttons Tag Property to determine which control to use, I have used this in the past for dynamically generated controls.
private void Form1_Load(object sender, EventArgs e)
{
// Create 3 buttons
Button button1 = new Button();
button1.Name = "button1";
button1.Tag = 1; //note the Tag property being used
tableLayoutPanel1.Controls.Add(button1, 0, 0);
Button button2 = new Button();
button1.Name = "button2";
button2.Tag = 2;
tableLayoutPanel1.Controls.Add(button2, 0, 0);
Button button3 = new Button();
button3.Name = "button3";
button3.Tag = 3;
tableLayoutPanel1.Controls.Add(button3, 0, 0);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
foreach (Control c in tableLayoutPanel1.Controls) //iterate through controls
{
if ((int)c.Tag == 1) //if Tag is equal then process
{
if (c is Button)
{
if (string.IsNullOrEmpty(textBox1.Text))
{
((Button)c).Enabled = false;
}
else
{
((Button)c).Enabled = true;
}
break; //if you have multiple controls to process remove this
} //and assign the same tag to the controls you want processed
}
}
}

Categories

Resources