add event to all labels in form [duplicate] - c#

This question already has answers here:
Apply same event to every project button in a C#
(2 answers)
Closed 3 years ago.
I want to add click,mouseleave and mouseenter event to all labels in the form using code below. But i call the addeventtoalllabels on form_load but it wont add event to labels.
public void setColor()
{
if (clickedLabel != default(Label))
clickedLabel.BackColor = Color.Yellow;
//Resetting clicked label because another (or the same) was just clicked.
}
void addeventtoalllabels()
{
foreach (Label c in this.Controls.OfType<Label>())
{
try
{
c.Click += (sender, e) => {
setColor();
Label theLabel = (Label)sender;
clickedLabel = theLabel;
};
c.MouseEnter += (sender, e) =>
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel)
theLabel.BackColor = Color.Red;
};
c.MouseLeave += (sender, e) =>
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel)
theLabel.BackColor = Color.Yellow;
};
}
catch { }
}
}

It sounds like the problem is that some of your labels are inside other container controls, so they aren't getting iterated over when you do this.Controls.OfType<Label>() (all Control objects have a Controls collection).
One way to work around this is to recursively look through all the controls' Controls collections so you can find the child Label objects that belong to other container controls.
Below are 3 methods:
AddEventsToLabel takes in a Label control and adds events to it.
AddEventsToChildLabels takes in a Control argument and checks to see if it's a Label. If it is, it passes it to the method in #1 above. Otherwise, it recursively calls itself for each child control of the one that was passed in.
AddEventsToAllLabels is used to kick off the process - this method calls the method in #2 above, passing in the Form itself as the parent control (this).
This way we end up iterating over every control on the form, including all those inside other container controls:
private void AddEventsToAllLabels()
{
AddEventsToChildLabels(this);
}
private void AddEventsToChildLabels(Control parent)
{
if (parent is Label)
{
AddEventsToLabel(parent as Label);
}
else
{
foreach (Control control in parent.Controls)
{
AddEventsToChildLabels(control);
}
}
}
private void AddEventsToLabel(Label label)
{
label.Click += (sender, e) => {
SetColor();
Label theLabel = (Label)sender;
clickedLabel = theLabel;
};
label.MouseEnter += (sender, e) =>
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel) theLabel.BackColor = Color.Red;
};
label.MouseLeave += (sender, e) =>
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel) theLabel.BackColor = Color.Yellow;
};
}
Note that it might be better to first remove the event handler before adding it, in case this method gets called more than once. Otherwise, if you hook the same event hander to the same event more than once, each time that event is raised, the handler will execute the number of times that it was added.
For example:
private void AddEventsToLabel(Label label)
{
label.Click -= LabelClick;
label.MouseEnter -= LabelMouseEnter;
label.MouseLeave -= LabelMouseLeave;
label.Click += LabelClick;
label.MouseEnter += LabelMouseEnter;
label.MouseLeave += LabelMouseLeave;
}
private void LabelClick(object sender, EventArgs e)
{
SetColor();
Label theLabel = (Label)sender;
clickedLabel = theLabel;
}
private void LabelMouseEnter(object sender, EventArgs e)
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel) theLabel.BackColor = Color.Red;
}
private void LabelMouseLeave(object sender, EventArgs e)
{
Label theLabel = (Label)sender;
if (theLabel != clickedLabel) theLabel.BackColor = Color.Yellow;
}

Related

C# WPF TextBox not focusing

I made a method what adds a TextBox to a Grid, but when i set it to focus it just won't.
This is the code what makes the textBox, and adds to the grid:
public static TextBox TextEditor(this FrameworkElement obj, Grid parent)
{
Label text = obj as Label;
TextBox edit = new TextBox();
edit.Text = text.Content.ToString();
edit.VerticalContentAlignment = VerticalAlignment.Center;
edit.Margin = obj.Margin;
edit.SetSize(obj);
edit.HorizontalAlignment = HorizontalAlignment.Left;
edit.VerticalAlignment = VerticalAlignment.Stretch;
edit.FontSize = 15;
parent.Children.Add(edit);
edit.KeyDown += (s, e) =>
{
if(e.Key == Key.Enter)
{
text.Content = edit.Text;
parent.Children.Remove(edit);
}
if(e.Key == Key.Escape)
{
parent.Children.Remove(edit);
}
};
parent.SizeChanged += (s, e) =>
{
edit.SetSize(obj);
};
edit.Focusable = true;
return edit;
}
Here the code what calls the TextEditor method and set the textbox in focus, or at least tries it:
private void Type_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Type.TextEditor(PreviewItems).Focus();
}
The Type variable is a Label. I searched a lot but couldn't find a solution. Why doesn't it work?
I tried every method in this post:
WPF: Can't get my control to take focus

C#: How to MouseHover on a group of objects and MouseLeave event when you leave the entire group [duplicate]

This question already has an answer here:
How can a hover effect be created for a grouping of controls?
(1 answer)
Closed 4 years ago.
I have a few objects in a groupBox in Visual Studio such as a few buttons. I have a label that pops up when I enter the groupBox and disappears when I leave it. However, when I hover over a button in this groupBox, the label disappears as the MouseLeave event only corresponds to the groupBox.
Is there anyway to have all of these objects grouped together so when I hover on anything in the groupBox the label stays and when I leave the groupBox altogether the label disappears? I just want an elegant way to do this.
Thanks so much for your help!
This is different than How can a hover effect be created for a grouping of controls? because I'd like a different result than what this person wants and also I tried something similar and it didn't work.
Unfortunately you can not add objects by groupbox but you can add them as a list of the control type of itself.
here you go.
private void Form1_Load(object sender, EventArgs e)
{
TextBox[] textboxes = new TextBox[] { textBox1 , textBox2, textBox3 };
Button[] buttons = new Button[] { button1 };
foreach (TextBox tbox in textboxes)
{
tbox.MouseEnter += new System.EventHandler(textbox_MouseEnter);
tbox.MouseLeave += new System.EventHandler(textbox_MouseLeave);
}
foreach (var button in buttons)
{
button.MouseEnter += new System.EventHandler(btn_MouseEnter);
button.MouseLeave += new System.EventHandler(btn_MouseLeave);
}
}
private void btn_MouseEnter(object sender, System.EventArgs e)
{
var Button = (Button)sender;
button1.BackColor = Color.Red;
//label show
}
private void btn_MouseLeave(object sender, System.EventArgs e)
{
var Button = (Button)sender;
button1.BackColor = SystemColors.Control;
//label hide
}
private void textbox_MouseEnter(object sender, System.EventArgs e)
{
var textbox = (TextBox)sender;
textbox.BackColor = Color.Red;
//label show
}
private void textbox_MouseLeave(object sender, System.EventArgs e)
{
var textbox = (TextBox)sender;
textbox.BackColor = SystemColors.Control;
//label hide
}
GIF IMAGE OF WORKING : GIF
You could do something like this,
//Add new event handlers on appropriate location in your code (perhaps in the load event of the form?)
groupBox1.MouseEnter += new EventHandler(MouseEnteredGroupBox);
groupBox1.MouseLeave += new EventHandler(MouseLeftGroupBox);
In the MouseEnter event handler you change the state of your controls which you want to show.
private void MouseEnteredGroupBox(object sender, EventArgs e)
{
//Add controls to be shown when entering the groupbox
button1.Visible = true;
}
Add this method to check if your cursor is inside of your groupbox area
private bool IsAboveGroupBox(GroupBox gb)
{
Point cursorPos = PointToClient(Cursor.Position);
bool resultX = (cursorPos.X > gb.Location.X && cursorPos.X < gb.Location.X + gb.Size.Width) ? true : false;
bool resultY = (cursorPos.Y > gb.Location.Y && cursorPos.Y < gb.Location.Y + gb.Size.Height) ? true : false;
return resultX && resultY;
}
Finally in the MouseLeave event handler you call the method
private void MouseLeftGroupBox(object sender, EventArgs e)
{
if (!IsAboveGroupBox(sender as GroupBox))
{
//Add controls to be hidden when leaving the groupbox
button1.Visible = false;
}
}
EDIT: Else you could just view your controls on the MouseEnter event on groupbox and hide your controls on the Forms MouseEnter event?

Making labels in array change backcolor on click using C# in Windows Forms

How can I change the BackColor of a label in an array when I click on it? Since there are multiple elements, I cannot manually activate each event for each individual label.
for (int i = 0; i < 361; i++)
{
board[i] = new Label();
board[i].Parent = pictureBox1;
board[i].Location = new Point(x, y);
board[i].Name = "label" + i;
board[i].BackColor = Color.Black;
//set size of labels
board[i].Size = new Size(30, 30);
//initialize click event handler
this.board[i].Click += new System.EventHandler(this.labelClick);
}
private void labelClick (object sender, EventArgs e)
{
foreach (Label i in board)
{
if (iteration % 2 == 0)
{
i.BackColor = Color.Black;
iteration++;
}
else if(iteration % 2 == 1)
{
i.BackColor = Color.White;
iteration++;
}
}
}
There are a few ways you can handle this. One way is to wire each Labels Click event up to the same event:
this.label1.Click += new System.EventHandler(this.label_Click);
this.label2.Click += new System.EventHandler(this.label_Click);
this.label3.Click += new System.EventHandler(this.label_Click);
In the label_Click event you can set the BackColor of each label OR just the one you clicked on.
// This will set each label's BackColor to Red.
private void label_Click(object sender, EventArgs e)
{
foreach (Label label in labelArray)
{
label.BackColor = Color.Red;
}
}
// This will set just the clicked on Label's BackColor to Red.
private void label_Click(object sender, EventArgs e)
{
Label label = sender as Label;
if (label != null)
{
label.BackColor = Color.Red;
}
}
var labels = new[]
{
// labels here
};
foreach (var label in labels)
{
label.Click += (sender, args) =>
{
var lbl = sender as Label;
Debug.Assert(lbl != null);
lbl.BackColour = Colors.Pink;
};
}

Different events using the same code

I have 2 events:
this.lblSettings.MouseEnter += new System.EventHandler(this.HookEvent);
this.lblSettings.MouseLeave += new System.EventHandler(this.HookEvent);
They call this one Method:
private void HookEvent(object sender, EventArgs e)
{
try
{
string method = System.Reflection.MethodBase.GetCurrentMethod().Name;
Label label;
if (sender is Label)
{
//Get the event. eg: MouseEnter, MouseLeave
label = (Label)sender;
label.BackColor = Color.FromArgb(30, 30, 30);
}
else if (sender is PictureBox)
{
PictureBox picBox;
picBox = (PictureBox)sender;
Control control = picBox.Parent;
if (control is Panel)
{
foreach (Control ctrl in control.Controls)
{
if (ctrl is Label)
{
label = (Label)ctrl;
label.BackColor = Color.FromArgb(30, 30, 30);
break;
}
}
}
}
}
catch (Exception ex)
{
throw;
}
}
In the LABEL part, where I have the comment: "//Get the event. eg: MouseEnter, Mouseleave",
I want to see if this is the MouseEnter or the MouseLeave event being executed, because I want to do different things for each event.
Not possible as those events do not use EventArgs sub classes.
Edit:
you could of course create a new StackTrace() object and check the frames method name to see which event it is :)

Child elements events listener

On a C# Winform application. Imagine that I have a Panel with some labels inside.
How can I listen all click events from this labels in Panel click event?
You can do this programmatically by calling the following code in your Form_Load event handler or any other suitable event handler.
foreach (Label label in panel1.Controls.OfType<Label>())
{
label.Click += LabelOnClick;
}
And then perform your operations in the event handler:
private void LabelOnClick(object sender, EventArgs eventArgs)
{
MessageBox.Show("Label In Panel Clicked");
}
Why not add a extra event handler to all the Control of Type Button within a Panel?
Sample Code :
private void SetupButtonClickListenerForPanel1()
{
panel1.Click += ListenForAllButtonClickOnPanel1;
foreach (Control control in panel1.Controls)
{
var tb = control as Button;
if (tb != null)
{
tb.Click += ListenForAllButtonClickOnPanel1;
}
}
}
private void ListenForAllButtonClickOnPanel1(object sender, EventArgs eventArgs)
{
//
Button tb = (Button) sender; // casting will fail if click is on Panel1 itself!
MessageBox.Show(tb.Name);
}
Linq way to add Handler :
private void SetupButtonClickListenerForPanel1()
{
panel1.Click += ListenForAllButtonClickOnPanel1;
foreach (var tb in panel1.Controls.OfType<Button>())
{
tb.Click += ListenForAllButtonClickOnPanel1;
}
}
If your Labels are children of the panel, a listener for the Click Event on the panel will listen all non redefined listeners of his children.
Example Code:
{
//Form init
panel1.Click += new System.EventHandler(this.panel1_Click);
....
}
private void panel1_Click(object sender, EventArgs e)
{
//The clicked label will be sender.
Label l = (Label) sender; //Should be a safe cast. Will crash if sender is not a label
}

Categories