Recognizing sender button control in click event - c#

I made a custom button that has a field named Data.
I add this button programatically during runtime to my winform and on adding I also define a click event for them. Well, Actually I only have one method and I subscribe the newly added buttons to this method.
But in the click event I want to access this Data field and show it as a message box, but it seems that my casting is not right:
CustomButton_Click(object sender, EventArgs e)
{
Button button;
if (sender is Button)
{
button = sender as Button;
}
//How to access "Data" field in the sender button?
//button.Data is not compiling!
}
UPDATE:
I am sorry, I ment with "is not compiling" that .Data does not show up in intelisense...

You need to cast to the type of your custom class that has the Data field.
Something like:
YourCustomButton button = sender as YourCustomButton;

Assuming your custom button type is CustomButton, you should do this instead:
CustomButton_Click(object sender, EventArgs e){
CustomButton button = sender as CustomButton;
if (button != null){
// Use your button here
}
}

If you dont want to set a variable the simple way to do is:
((CustomButton)sender).Click
or whatever you want.

I found a funny check assignment in a win forms project on Github:
private void btn_Click(object sender, EventArgs e){
// here it checks if sender is button and make the assignment, all in one shot.
// Bad readability, thus not recommended
if (!(sender is Button senderButton))
return;
var _text = senderButton.Text;
...

Related

Check if RadioButton is Checked from Checkchanged event

I need to check if the RadioButton is checked from the checkchanged event
private void radioButton6_CheckedChanged_2(object sender, EventArgs e)
{
if(radioButton6.Checked)
{
}
}
Is this the properway to do it? Can i access the CheckBox state from the sender object?
Is this the properway to do it?
That depends. If you need each radio button to be very much distinguished. Meaning: You really need to check inside the event method:
if(radioButton6.Checked)
Then this is the way to go. Another case where this can be applied is when you have registered an individual event handler for each radio button. Then you can access the button directly, because in this case the sender will always be e.g. radioButton6.
Can i access the CheckBox state from the sender object?
Yes you can. It might be adviseable in this case: If you decide to register the same method to a bunch of different radio button events then you could use the sender and cast it. This might save you a lot of double code.
private void radioButton6_CheckedChanged_2(object sender, EventArgs e)
{
RadioButton button = sender as RadioButton;
if(button?.Checked == true)
{
}
}
In such a case you can use the Tag property of the RadioButton to distinguish them. Set it in the beginning and then you can check for it.

how to retrieve text of buttons clicked in windows form with one single method

I have a windows form application with multiple buttons. I need to retrieve the text property of any button clicked in order to create a query to the database. the only way I know is to create a button click event and cast the sender as button then do a switch case for each button Id which seems very hectic since I probably will have more than 100 buttons in the entire application. So my question is there a generic key press method I can create which can retrieve the text property of any button pressed/clicked on the form? Please excuse me if the question is not very clear. Any help will be appreciate
Use a single click event handler for all similar kind of buttons. This way there will be click event subscribed for every button but only one method which will be executed for all buttons. You can determine which button was pressed as follows.
Using sender object as follows;
private void button_Click(object sender, EventArgs e)
{
var buttonText = ((Button)sender).Text;
//Query using buttonText
}
Update:
Above answer will still require you to subscribe click event for each button. If you don't want that then have a look at following approach;
You could use (ClickTransparentButton or) disable (Enabled=false) all these buttons and add click event on parent Form. Once you get click event you can get button which was clicked as follows;
private void Form1_Click(object sender, EventArgs e)
{
var p = PointToClient(Cursor.Position);
var control = GetChildAtPoint(p);
if(control is Button)
{
var buttonText = ((Button)control).Text;
//Query using buttonText
}
}
But this has few disadvantages such as, you will not be able to operate these buttons using keyboard.
and more...
Create some function as buttons click handler:
private void buttonClickHandler(object sender, EventArgs e)
{
string buttonName = (sender as Button).Text;
}
2A. Connect Click event of every button to this handler.
2B. To automate connection of button click handler use something like that:
private void connectButtonsHandlers()
{
foreach(var c in this.Controls)
{
if(c is Button)
{
(c as Button).Click += buttonClickHandler;
}
}
}
Add this code to form constructor to perform connection at program start.

Route multiple buttons to the same routine

I have 10 buttons, 0-9 (button0, button1, button2...). When I click any of these buttons, I would like to perform the same routine on them. I would like to know how to, upon clicking of any of these buttons, direct them to the routine below.
private void button0_Click(object sender, EventArgs e)
{
int newValue;
newValue = Convert.ToInt32(Button.text);
}
I have already gone into the properties of each button, then events, and changed the click event to button0_Click (I would have thought this would add "handles button1.click, button2.click, etc." after "private void button0_Click(object sender, EventArgs e)" but if it does that in the background, that's ok as long as it works.)
I also need to know how to identify the button that has been pressed, which is where I'm at with "Convert.ToInt32(Button.text)" (e.g. button2.text = "2").
You can select the same event handler for all the buttons in the designer (in the event tab of the properties window, select the event and there'll be a drop down with all your defined event handlers).
To get which button has been clicked on, cast the sender argument to a Button and you'll have it.
Button button = (Button)sender;
int value = int.Parse( button.Text );
Edit: Also, the "Handles control.event" syntax only exists in Visual Basic.
Edit: Check out the generated code (Form1.Designer.cs, for example) to see how the events are hooked up.
The C# language doesn't use handles to bind events (as VB does). The code for the actual binding is in the generated code for the form, i.e. in the background as you put it.
The sender property is a reference to the control where the event happened. You just need to cast it to the actual type of the control:
private void button0_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
int newValue = Convert.ToInt32(button.text);
}
As an alternative to using the text of the button (for example if you want to translate the application to different languages, or simply don't want to rely on the text), you can put whatever you like in the Tag property of each button, and retrieve it in the event handler.
You could wire them all up to the same event handler an extract the button from sender e.g.
private void button0_Click(object sender, EventArgs e)
{
var button = sender as Button
if (button != null)
{
int newValue = Convert.ToInt32(Button.text);
}
}

Windows Forms - get Text value from object of type button

I have a Windows form named Form1 and panel within this form named panel1. I use the panel only to place buttons there so that I can group them and work with them separately from the other buttons in my Form1. For the purpose of my program I need to handle every button click made from the buttons inside panel1. For this purpose I use the same code snippet:
public Form1()
{
InitializeComponent();
// Set a click event handler for the button in the panel
foreach (var button in panel1.Controls.OfType<Button>())
{
button.Click += HandleClick;
}
}
What I need to do is to have a way to identify which button exactly has been clicked. For this purpose I played a little bit with my handler method:
private void HandleClick(object o, EventArgs e)
{
MessageBox.Show("HI" + o.ToString());
}
which gave me some hope because I get this:
It's the second part - Text: button4 which is actually enough information to continue with my work. But I can't find a way to get this piece of information without some complicated string manipulations. So is there a way to get this or other unique information about the button been clicked given the way I have written my code?
private void HandleClick(object sender, EventArgs e)
{
var btn = sender as Button;
if (btn != null)
{
MessageBox.Show(btn.Text);
}
}
One option is to cast the object to a Button, but rather than doing the casting you can change how the event handler is assigned so that you don't need to cast in the first place:
foreach (var button in panel1.Controls.OfType<Button>())
{
button.Click += (_,args)=> HandleClick(button, args);
}
Then just change the signature of HandleClick to:
private void HandleClick(Button button, EventArgs e);
You need to cast sender to the Button class so you can access its properties:
Button b = (Button)sender;
MessageBox.Show(b.Text);

Radio button checked changed event fires twice

Please read my question its not a duplicate one.
I've three radio buttons on windows form and all these buttons have common 'CheckedChanged' event associated. When I click any of these radio buttons, it triggers the 'CheckedChanged' event twice.
Here is my code:
private void radioButtons_CheckedChanged(object sender, EventArgs e)
{
//My Code
}
I inserted the breakpoint and the whole code within this event iterates twice.
Please tell me why it is behaving like this?
As the other answerers rightly say, the event is fired twice because whenever one RadioButton within a group is checked another will be unchecked - therefore the checked changed event will fire twice.
To only do any work within this event for the RadioButton which has just been selected you can look at the sender object, doing something like this:
void radioButtons_CheckedChanged(object sender, EventArgs e)
{
RadioButton rb = sender as RadioButton;
if (rb != null)
{
if (rb.Checked)
{
// Only one radio button will be checked
Console.WriteLine("Changed: " + rb.Name);
}
}
}
To avoid it, just check if radioButton is checked
for example:
private void radioButton1_CheckedChanged(object sender, EventArgs e)
{
if (radioButton1.Checked)
//your code
}
CheckedChanged is raised whenever the Checked property changes. If you select a RadioButton then the previously selected RadioButton is unchecked (fired CheckedChanged), and then the new RadioButton is checked (fired CheckedChanged).
It's triggering once for the radio button transition from checked to unchecked, and again for the radio button transitioning from unchecked to checked (i.e. any change in checked state triggers the event)
You could set the AutoCheck property true for each RadioButton then catch the Click event instead of the CheckChanged event. This would ensure that only one event is fired, and the logic in the handler can cast the sender to type RadioButton if needed to process the click. Often the cast can be avoided if the handler logic is simple. Here is an example which handles three controls, rbTextNumeric, rbTextFixed and rbTextFromFile:
private void rbText_Click(object sender, EventArgs e)
{
flowLayoutPanelTextNumeric.Enabled = rbTextNumeric.Checked;
txtBoxTextFixed.Enabled = rbTextFixed.Checked;
flowLayoutPanelTextFromFile.Enabled = rbTextFromFile.Checked;
}
{
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
int click = 0;
private void radioButton1_Click(object sender, EventArgs e)
{
click++;
if (click %2==1)
{
radioButton1.Checked = true;
}
if (click %2==0)
{
radioButton1.Checked = false;
}
if (radioButton1.Checked==true)
{
label1.Text = "Cheked";
}
if (radioButton1.Checked==false)
{
label1.Text = "Uncheked";
}
}
}
}
The other answers are correct but miss the reason for the underlying problem.
When a radio button is checked the first event sent is the change from the unchecked item
however if you check its state by its control name you will still see its old checked status because the form has not been updated yet. To see its true status you need to cast the sender object.
This allows you to perform any actions relating to the condition which is being deselected should you need to do so.
In the not uncommon scenario below multiple radio buttons are sent to the same handler event.
Simply checking the state of the sender for checked will not work here as we need to perform different actions depending on which radio button has been pressed.
So first we ignore any sender that has just been unchecked.
then we identify the checked sender by control name to process the correct action.
private void ModeChangedExample(object sender, EventArgs e)
{
// multiple radio buttons come here
// We only want to process the checked item.
// if you need to something based on the item which was just unchecked don't use this technique.
// The state of the sender has not been updated yet in the form.
// so checking against rdo_A check state will still show it as checked even if it has just been unchecked
// only the sender variable is up to date at this point.
// To prevent processing the item which has just been uncheked
RadioButton RD = sender as RadioButton;
if (RD.Checked == false) return;
if (rdo_A.Name == RD.Name)
{
//Do stuff
}
if (rdo_B..Name == RD.Name)
{
// Do other stuff
}
if (rdo_C.Name == RD.Name)
{
// Do something else
}
}
This problem of double checking happens when there is a series of RadioButton Clicks in succession.I had this same problem.The last click will give two results.To overcome this i made a dummy click in the end.The double click stopped.Try this method.
Venkatraman

Categories

Resources