C# - Defining a Method for a Label without specifying Label name - c#

I have a form that has a set of labels that can be clicked - See Screenshot (Labels 93 to Label 21 on the Player side and labels 10 to 22 on the computer side).
All I want to do is change the label back colour when the control is clicked. This I have figured out.
My question is more about clean code. Instead of having
private void Playerlabel_Click(object sender, EventArgs e)
{
lblPlayerCardInt.BackColor = Color.FromArgb(219, 255, 248);
}
private void Playerlabel2_Click(object sender, EventArgs e)
{
lblPlayerCardStrength.BackColor = Color.FromArgb(219, 255, 248);
}
//repeat 5 times and then another 5 times for the computer labels.
Is there a way of defining a method so that no matter if I click the label or the computer clicks it, the method of highlighting the label is called.
I'm think something along the lines of
public void HighlightLabel()
{
foreach (Control x in this.Controls)
{
if (x is Label)
{
((Label)x).BackColor = Color.FromArgb(219, 255, 248);
}
}
}
Is this the right approach? It may seem like an obvious question, but new to programming in C#/OOP so want to be sure I'm doing it the correct way.

Yes you can set only 1 Click event-handler for all those labels:
Step 1:
private void lbl_Click(object sender, EventArgs e)
{
Label lbl = sender as Label;
lbl.BackColor = Color.FromArgb(219, 255, 248);
}
Step 2:
If you create labels on design time then do the following for each label:
On Form designer, select label then open View > Properties > Events tab
Select above lbl_Click event-handler from the dropdown list
OR
If your create labels programatically then use this instead:
lblPlayerCardInt.Click += new EventHandler(lbl_Click);
lblPlayerCardStrength.Click += new EventHandler(lbl_Click);
...

Seeing as all you're doing is setting the backcolor each time why not just have 1 method and do something like:
private void label_Click(object sender, EventArgs e)
{
Label mylabel = (Label) sender;
mylabel.backcolor = Color.FromArgb(219, 255, 248);
}
You can then just put Label_Click in as the click event for each label rather than doing a separate method for each label.
However, if you want to do more based on the label you can use the sender to determine the label clicked. Something like this:
private void label_Click(object sender, EventArgs e)
{
Label mylabel = (Label) sender;
//Determine which label has been clicked by name or id for example
switch(myLabel.Name)
{
case "lblPlayerCardint":
//Do something
break;
}
}

You could cast the event sender object to a label
private void label_Click(object sender, EventArgs e)
{
Label lblClicked=sender as Label;
lblClicked.BackColor = Color.FromArgb(219, 255, 248);
}

You could use OfType which is part of the System.Linq namespace:
foreach(Label lbl in this.Controls.OfType<Label>())
lbl.BackColor = Color.FromArgb(219, 255, 248);

This should do the trick for you and register the same click event for all your labels on the form.
this.Controls
.OfType<Label>()
.AsParallel()
.ForAll(x => x.Click += (o,e) => x.BackColor= Color.FromArgb(219, 255, 248));

Related

Event that would listen to any label click in form

Well, I'm making a chess game that's based on labels. I need to listen for label click, so when user clicks on an label, I get the name of label he clicked. I know I can do it for each label, but is there an universal event that would help me do the same thing for all of them in one event / loop?
Suppose you have taken 64 labels.
In windows form, on click event of Label1 you will write following code:
private void Label1_Click(object sender, EventArgs e)
{
var label = sender as Label;
MessageBox.Show(label.Name);
}
For remaining 63 Lables, In Design view, select all 63 lables by using Ctrl key --> Go to Property window --> Under Event option select Click option --> From dropdownlist select 'Label1_Click' option.
Just finish & run the application.
You can use a Panel
structure to group your labels and then call the desired event on that Panel, so it will trigger whenever you click one of it's elements.
Another solution would be to identify your label with the coordinates of the mouse click (the amount of code that requires depends how you placed them of course).
Like mentioned in the comments you can assign one event to all...
List<Label> lbls = this.Controls.OfType<Label>().ToList();
foreach (var lbl in lbls)
{
lbl.Click += lbl_Click;
}
void lbl_Click(object sender, EventArgs e)
{
Label lbl = sender as Label;
MessageBox.Show(lbl.Name);
}
You can assign these methods to every label you need to manage in the VS form designer (you go to events of controls, at the click line and select the method in the list instead of double click on it):
private void Label_Click(object sender, EventArgs e)
{
var nameLabel = ( sender as Label )?.Name ?? "Error";
// ...
}
private void Label_Enter(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Hand;
}
private void Label_Leave(object sender, EventArgs e)
{
( sender as Label ).Cursor = Cursors.Default;
}
Cursor change added for convenience if you want.
If you want to dynamically assign events, you can use the #caner answer, and you can group all in a panel to parse Panel.Controls and assign event.
You can create a custom label class that inherits from Label. You can then subscribe to the Click event of the base class and do your thing.
public class MyLabel : Label
{
public MyLabel()
: base()
{
Click += ProcessClickEvent;
}
private void ProcessClickEvent(object sender, System.EventArgs e)
{
// Do what you want to do
}
}

How to select a perticular cell in table layout and paint with different color

I have created a Table layout in windows forms as shown in figure, i have added a right mouse button click Menu to my table, i want to color the cell when i right click on the perticuler cell, so how can i do it.
When i click add device the cell should paint to green color,
When i click delete device it should show default color,
When i click fire the cell should be painted with red color
so on
The below is my form and table layout
Hi there i dont have what you looking for but,
TableLayoutPanels don't really have 'cells' as such and are really meant to be a container for controls. This means you can't really retrieve individual rows, columns or cells. An alternative would be to use panels and put individual click events on each of these.
However if you're determined that you want to use TableLayoutPanels, you can use the XY coordinate of where the mouse click occurred on the TableLayoutPanel from EventArgs. And determine which block it is, since you've got evenly spread rows/columns.
For example if you have all the cells the same size and the the TableLayoutPanel is docked in the form this will get the selected Cell.:
Point selectedCell = new Point();
private void tableLayoutPanel1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
//show contextMenuStrip
selectedCell = new Point(e.X / (tableLayoutPanel1.Width / tableLayoutPanel1.ColumnCount), e.Y / (tableLayoutPanel1.Height / tableLayoutPanel1.RowCount));
}
}
I got the answer for my question it can be done as shown below
First we need to find the label control(sender) which has sent the event as follows
private void AssignClickEvent()
{
foreach (Control c in tableLayout.Controls.OfType<Label>())
{
c.MouseClick += tablelayout_MouseClick;
addDevice.Click += addDevice_Click;
deleteDevice.Click += deleteDevice_Click;
fire.Click += fire_Click;
fault.Click += fault_Click;
suppress.Click += suppress_Click;
}
}
have a globle varible of pointer control
public Label h = new Label();
then we need to copy the sender to the control
private void tablelayout_MouseClick(object sender, MouseEventArgs e)
{
Label l = (Label)sender;
if (e.Button == MouseButtons.Right)
{
h = l;
num = l.Text;
m.MenuItems.AddRange(new MenuItem[] { addDevice, deleteDevice, fire, fault,suppress });
tableLayout.ContextMenu = m;
m.Show((Control)(sender), e.Location);
}
}
then use global control `h' to set color to the control
public void addDevice_Click(object sender, EventArgs e)
{
try
{
h.BackColor = Color.Green; ;
comport.Write("AB");
comport.Write(num);
comport.Write(" ");
stausLable.Text = "Device "+num+" added";
comport.WriteLine("000000000000");
}
catch (InvalidOperationException )
{
stausLable.Text = "Open communication port";
}
}
There is an easier way without having to implement those events as well as the extra variables. Assuming the contextmenu is named 'DeviceActionsContextMenu' and is linked to the label controls (as per your comment), Implement the toolstrip Item's click event -
private void addDeviceToolStripMenuItem_Click(object sender, EventArgs e)
{
(contextMenuStrip1.SourceControl as Label).BackColor = Color.Green;
}
Or Implement the contextmenu's Item clicked event -
private void DeviceActionsContextMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
if (e.ClickedItem == addDeviceToolStripMenuItem)
{
(contextMenuStrip1.SourceControl as Label).BackColor = Color.Green;
}
}

Control hover color

Sorry, this is kinda beginner question but I'm not getting through.
I have a Windows Forms Applicaton with 4 panel controls on it. Now I want that the panels change their background when the user hovers with the mouse. I have tried following:
private void Panel1_MouseIn(object sender, EventArgs e)
{
panel1.BackColor = Color.Red;
}
private void Panel1_MouseOut(object sender, EventArgs e)
{
panel1.BackColor = Color.Blue;
}
That is working fine, but because I have 4 panels and not one I would have to add 6 more functions like this... The I tried to make one single function for all of them but event sender does not have an accessible BackColor property.
Is there a way to make one single MouseIn function for all panels?
If yes, how?
YOu should cast it:
private void Panel_MouseIn(object sender, EventArgs e)
{
Panel pan = sender as Panel;
pan.BackColor = Color.Red;
}
And use this one function for all 4 panels as event handler
You can cast your sender-object to a Panel like
Panel panel = (Panel)sender;
if(panel != null)
// Set the BackColor
You should first cast the sender object to Panel :
Panel panel = sender as Panel;
if (panel == null)
return;
panel.BackColor = Blue;
You could define an EventHandler for MouseIn and MouseOut and then
private void Panel1_MouseIn(object sender, EventArgs e)
{
Panel p = sender as Panel;
if(p == panel1){
//set color
}
else if(p == panel2){
//set color
}
...
}
The same for MouseOut
Inside mouse in and function remove all the code you have placed and write the one simple line of code below
And try it it will work
((Control)sender).BackColor = Color.Red;

Event handler for groupBox with radioButtons in C#

I have some radionButtons in groupBox and I need to do action what I could call "one of radiobuttons.checked changed" or find out from radiobutton what index is changed.
I've tryed to find it in list of events but I couldn't find the right one.
Edit:
To make it more clear: I need to know if exist some handel for what I'll write handler method for the goupBox not for single radioButton. I know how to use radiButton.checkedChanged, but it's not what I'm finding ..
Or differently I need to know what options have the groupBox in monitoring what happens inside this groupBox - I mean only the handlers for the groupBox. I'm finding handler "in the group box is something happens" or simimilar if any exist.
It's in WFA (Windows Presentation Application) in Visual studio 2012.
I think what you want to do is wire up all of the RadioButtons' CheckedChanged event to the same handler.
public Form1()
{
radioButton1.CheckedChanged += new EventHandler(radioButtons_CheckedChanged);
radioButton2.CheckedChanged += new EventHandler(radioButtons_CheckedChanged);
// ...
}
private void radioButtons_CheckedChanged (object sender, EventArgs e)
{
RadioButton radioButton = sender as RadioButton;
if (radioButton1.Checked)
{
// Do stuff
}
else if (radioButton2.Checked)
{
// Do other stuff
}
}
Nothing built in for that as far as I'm aware.
Set the tag property to some sort of indicator (0 to n) will do.
Add a CheckChangedHandler
Point all the buttons CheckChanged events at it.
then something like.
private void radioButtons_CheckedChanged (object sender, EventArgs e)
{
RadioButton radioButton = sender as RadioButton;
int buttonid = (int)radioButton.Tag;
switch (buttonid)
{
case 0 : // do something; break
}
}
If you've got a few of these I'd look at a radiogroup component.
I had the same problem: a group box named Button Type (gbxButtonType) with 6 radio buttons and another group box named Icon Type (gbxIconType) with 8 radio button. When the user selected one radio button from each group box, a MessageBox will appear with the selection applied after clicking the DisplayButton. My problem was that the group boxes didn't have a CheckedChanged event. The solution of AKN worked perfectly:
public Form1()
{
InitializeComponent();
for (int i = 0; i < gbxButtonType.Controls.Count; i++)
{
RadioButton rdb = (RadioButton)gbxButtonType.Controls[i];
rdb.CheckedChanged += new System.EventHandler(gbxButtonType_CheckedChanged);
}
for (int i = 0; i < gbxIconType.Controls.Count; i++)
{
RadioButton rdb = (RadioButton)gbxIconType.Controls[i];
rdb.CheckedChanged += new System.EventHandler(gbxIconType_CheckedChanged);
}
}
private void gbxIconType_CheckedChanged(object sender, EventArgs e)
{
if (sender == rdbAsterisk)
{
iconType = MessageBoxIcon.Asterisk;
}
else if (sender == rdbError)
{
iconType = MessageBoxIcon.Error;
}
...
else
{
iconType = MessageBoxIcon.Warning;
}
}
Similar to davenewza's answer (and likely should have been a comment, but I have insufficient reputation), but with the event firing only once for the entire group of radio buttons.
public Form1()
{
// Add a "CheckedChanged" event handler for each radio button.
// Ensure that all radio buttons are in the same groupbox control.
radioButton1.CheckedChanged += new EventHandler(radioButtons_CheckedChanged);
radioButton2.CheckedChanged += new EventHandler(radioButtons_CheckedChanged);
}
private void radioButtons_CheckedChanged (object sender, EventArgs e)
{
// Do stuff only if the radio button is checked (or the action will run twice).
if (((RadioButton)sender).Checked)
{
if (((RadioButton)sender) == radioButton1)
{
// Do stuff
}
else if (((RadioButton)sender) == radioButton2)
{
// Do other stuff
}
}
}
Groupbox will limit only one radio button checked
So Setp1: you can assign one "CheckedChanged" event handler to all you radio button
private void initRadio()
{
radio_button1.CheckedChanged += Radio_show_CheckedChanged;
radio_button2.CheckedChanged +=Radio_show_CheckedChanged;
}
And Setp2: implement this event handler like this (Filter by Radio Button's Text)
private void Radio_show_CheckedChanged(object sender, EventArgs e)
{
RadioButton radioButton = sender as RadioButton;
if (radioButton.Checked == true) { //limited only checked button do function
switch (radioButton.Text)
{
case "name1":
// do your stuff ...
break;
case "name2":
// do your stuff ...
break;
}
}
}
System.Windows.Forms.RadioButton.CheckedChanged
is the event you need
So do something like:
public Form1()
{
InitializeComponent();
this.radioButton1.CheckedChanged += new EventHandler(radioButton1_CheckedChanged);
}
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
// your action
}
I think your want to handle the selection of some radio buttons inside a groupbox using the groupbox control itself.
May be you wanted this basically to avoid code repetition.
(i.e) adding check change event for all the radio button in the designer which may be tedious when there are more control.
Since its already present under a group, why not use the group control object to manipulate controls with-in it and set the events.
This is how I understood your problem and hence the solution as indicated below.
Set a common handler for all radio button control in the group box
for (int i = 0; i < groupBox.Controls.Count; i++)
{
RadioButton rb = (RadioButton)groupBox.Controls[i];
rb.CheckedChanged += new System.EventHandler(evntHandler);
}
Inside the handler, you can determine which button was changed as indicated by others and do the necessary action.
//Here you go courtesy of Jock Frank Halliday
//^subscribe events to radio button check changed
private void seriesTxtBxEvent()
{
//Show txtBx
this.radBtn_RoomSeries.CheckedChanged += new EventHandler(showSeriesTxtBx_Event);
//Hide txtBx
this.radBtn_RoomNumber.CheckedChanged += new EventHandler(hideSeriesTxtBx_Event);
this.radBtn_RoomName.CheckedChanged += new EventHandler(hideSeriesTxtBx_Event);
this.radBtn_RoomLevel.CheckedChanged += new EventHandler(hideSeriesTxtBx_Event);
this.radBtn_RoomDep.CheckedChanged += new EventHandler(hideSeriesTxtBx_Event);
}
private void hideSeriesTxtBx_Event(object sender, EventArgs e)
{
tbx_SheetSeries.Visible = false;
}
private void showSeriesTxtBx_Event(object sender, EventArgs e)
{
tbx_SheetSeries.Visible = true;
}
//Form Start
void MainFormLoad(object sender, EventArgs e)
{
Control.ControlCollection locais = groupBoxLocalização.Controls;
foreach (CheckBox chkBox in locais)
{
chkBox.MouseUp += chkBoxLocais_MouseUp;
}
}
// Event
void chkBoxLocais_MouseUp(object sender, MouseEventArgs e)
{
//Tratar individualmente
CheckBox chk = (CheckBox)sender;
//ou para tratar todos objetos de uma vez
Control.ControlCollection locais = groupBoxLocalização.Controls;
foreach (CheckBox chkBox in locais) {
//chkBox....
}
}
You can maybe do it with Timer, but that's just bad for optimalization, the easy solution is that for every radiobutton you simply add only one function as ChekedChanged event.
Create a Checked event by double clicking on any of the radio buttons, copy the name of the method that Visual Studio creates for the event
Go to all radio buttons and change the event to the copied one from Properties Explorer > Events Section
In the generated method use the following code. This would fire event for all radio buttons but only "Do your thing" once
Code:
private void radioButtons_CheckedChanged (object sender, EventArgs e)
{
RadioButton rb = sender as RadioButton;
if (rb.Checked == false) return;
// Do your thing
}
Create Event Checked_Changed on one radio button from Designer Events list.
Add same event to each radio Button from dropdown in front of Checked_Changed
event of each radio
inside checked changed event use
private void CheckedChanged(object sender,EventArgs e)
{
var radio = groupBox.Controls.OfType<RadioButton>
().FirstOrDefault(r => r.Checked).Name;
}
you can get which radio is active now.

how to handle programmatically added button events? c#

I'm making a windows forms application using C#. I add buttons and other controls programmatically at run time. I'd like to know how to handle those buttons' click events?
Try the following
Button b1 = CreateMyButton();
b1.Click += new EventHandler(this.MyButtonHandler);
...
void MyButtonHandler(object sender, EventArgs e) {
...
}
Use this code to handle several buttons' click events:
private int counter=0;
private void CreateButton_Click(object sender, EventArgs e)
{
//Create new button.
Button button = new Button();
//Set name for a button to recognize it later.
button.Name = "Butt"+counter;
// you can added other attribute here.
button.Text = "New";
button.Location = new Point(70,70);
button.Size = new Size(100, 100);
// Increase counter for adding new button later.
counter++;
// add click event to the button.
button.Click += new EventHandler(NewButton_Click);
}
// In event method.
private void NewButton_Click(object sender, EventArgs e)
{
Button btn = (Button) sender;
for (int i = 0; i < counter; i++)
{
if (btn.Name == ("Butt" + i))
{
// When find specific button do what do you want.
//Then exit from loop by break.
break;
}
}
}
If you want to see what button was clicked then you can do the following once you create and assign the buttons. Considering that you create the button IDs manually:
protected void btn_click(object sender, EventArgs e) {
Button btn = (Button)sender // if you're sure that the sender is button,
// otherwise check if it is null
if(btn.ID == "blablabla")
// then do whatever you want
}
You can also check them from giving a command argument to each button.
Check out this example How to create 5 buttons and assign individual click events dynamically in C#
seems like this works, while adding a tag with each element of the array
Button button = sender as Button;
do you know of a better way?
In regards to your comment saying you'd like to know which button was clicked, you could set the .Tag attribute of a button to whatever kind of identifying string you want as it's created and use
private void MyButtonHandler(object sender, EventArgs e)
{
string buttonClicked = (sender as Button).Tag;
}

Categories

Resources