I know about this question but it does not addres my issue.
Suppose we have two buttons that do the very same thing (load csv file and feed the data in two variables) but on two different sets of variables. I can write two functions dedicated to both functions, but they will share too much common code.
How can I detect what button called the callback function to decide what set of variables to work on?
You can access the Button by casting the sender argument.
You should use an explicit cast instead of (the often seen) as operator, because it would correctly result in an InvalidCastException when the sender is unexpectedly not a Button.
private void button_Click(object sender, EventArgs e)
{
var button = (Button)sender;
// Use button properties to differentiate and load to your variables accordingly
}
Related
What do sender and eventArgs mean/refer to? How can I make use of them (for the scenario below)?
Scenario:
I'm trying to build a custom control with a delete function, and I want to be able to delete the control that was clicked on a page that contains many of the same custom control.
The sender is the control that the action is for (say OnClick, it's the button).
The EventArgs are arguments that the implementor of this event may find useful. With OnClick it contains nothing good, but in some events, like say in a GridView 'SelectedIndexChanged', it will contain the new index, or some other useful data.
What Chris is saying is you can do this:
protected void someButton_Click (object sender, EventArgs ea)
{
Button someButton = sender as Button;
if(someButton != null)
{
someButton.Text = "I was clicked!";
}
}
sender refers to the object that invoked the event that fired the event handler. This is useful if you have many objects using the same event handler.
EventArgs is something of a dummy base class. In and of itself it's more or less useless, but if you derive from it, you can add whatever data you need to pass to your event handlers.
When you implement your own events, use an EventHandler or EventHandler<T> as their type. This guarantees that you'll have exactly these two parameters for all your events (which is a good thing).
Manually cast the sender to the type of your custom control, and then use it to delete or disable etc. Eg, something like this:
private void myCustomControl_Click(object sender, EventArgs e)
{
((MyCustomControl)sender).DoWhatever();
}
The 'sender' is just the object that was actioned (eg clicked).
The event args is subclassed for more complex controls, eg a treeview, so that you can know more details about the event, eg exactly where they clicked.
'sender' is called object which has some action perform on some
control
'event' its having some information about control which has
some behavoiur and identity perform
by some user.when action will
generate by occuring for event add
it keep within array is called event
agrs
FYI, sender and e are not specific to ASP.NET or to C#. See Events (C# Programming Guide) and Events in Visual Basic.
I'm working on a project and I'm in a situation where the administrator needs to accept new users into the system. I've got a form that only admins can access, which shows a list of all the waiting applicants. I've found out how to create buttons at run time and how to add an event handler for the click event, but the handler requires a method by the same name to run.
Obviously I can't just put code for a method inside a for loop, unless I'm mistaken. How would I give the program the ability to support an potentially infinite amount of applicants?
void AcceptUsersAdminLoad(object sender, EventArgs e)
{
//FOR LOOP - To be finished. Will read an xml file to find out # to loop.
Button newButton = new Button();
newButton.Click += new System.EventHandler(newButtonClick);
newButton.Text = "Accept";
Panel1.Controls.Add(newButton);
}
private void newButtonClick (Object sender, System.EventArgs e){
}
This works, but as I've said, only for one button. As relatively painless as it would be to copy the method and append it's name with a number a hundred times, I'd prefer to find a way with support for more.
You can use that same method for all of your buttons! The sender parameter will tell you which button is the source, simply cast it to a button. You can store an ID of some sort in the .Tag() property of the button so you know who you are working with (when you create them, assign it).
private void newButtonClick (Object sender, System.EventArgs e){
Button btn = (Button)sender;
// ... do something with "btn" in here ...
}
Answer to the titular question: You don't create methods in a loop. You will occasionally create anonymous methods in a loop, but save that for later :).
To do what you want though: When you generate these buttons, they should all be pointing to the same event handler. The logic you want to run is the same, but the data is different.
How you get the data to the function is not trivial, one (hackish) way to do it is to store the related object (or its index) in the Tag property of the button, which you can then retrieve via the sender argument of the event handler.
In C# if you create an object on a button click, at the end of the click event, the object is no longer in scope. How do I create an object on the click of a button, but release it on the click of another button. Here is what I am trying to do:
Build an application that accepts user data and adds it to a database. The application contains two classes: Personal information and employer information. The personal information class object should be created when the "Start Application" button is pressed. The application then opens a tab that requests personal information. If the "Add Employer" button is selected, an instance of Employer is created. After they press submit at the end, it should close the one or two objects and return to the main menu. When the next person presses the button, it should go through the process again.
I can create objects on click or in the class itself, but how do you limit the life of the object between to button presses?
Thanks!
Use a class-scoped data member. Very quick example:
public class MyClass
{
private Foo foo;
private void Button1_Click(object sender, EventArgs e)
{
this.foo = new Foo();
}
private void Button2_Click(object sender, EventArgs e)
{
// I can access this.foo here. I can also dispose of it
// if it is IDisposable and/or I can set it to null.
// To check if button 1 was pressed, check to see if the object
// is null (if it is, button 1 wasn't pressed)
}
}
You can do this by defining one of the event handlers anonymously inside of the other event handler:
void button1_Click(object sender, EventArgs e)
{
Foo data = new Foo();
EventHandler handler = null;
handler = (s, args) =>
{
//Use Foo here
DoStuff(data);
button2.Click -= handler;
};
button2.Click += handler;
}
Note that we need to do some extra work to make sure to remove the event handler when it is clicked here. If you don't need to do that, then it does simplify the code.
Here the anonymous method is closing over the local variable, which will extend that variable's lifetime for the lifetime of the anonymous method. This approach, unlike those using a field, actually creates a variable who's lifetime lasts until the next button is clicked, and doesn't leave a variable lying around with a meaningless value before the first button is clicked or after the second is clicked.
Sounds like you're wanting to use properties?
Here's a link to MSDN, but there's lots out there if you just Google'C# properties'
I can create objects on click or in the class itself, but how do you limit the life of the object between to button presses?
Sadly you're pretty much stuck with putting it at class scope. There is no simply way to limit the scope of an object to just a few methods within a class. If your 2 event handlers can access your Employer, then so can every other method within the class. You just have to not use it.
However, out of curiosity I managed to hack around and produce the effect you want. I did a class with 2 event handlers, one for each button, as well as a private Employer variable.
public class ButtonHandler
{
private Employer employerData;
public void button1_Click(object sender, EventArgs e)
{
employerData = "set data here";
}
public void button2_Click(object sender, EventArgs e)
{
employerData = "use / clear data here";
}
}
Then I went to my Form.Designer.cs and manually changed the button.Click event handler from the default this.btnLoadPlaylist_Click to my functions within the ButtonHandler class above. The problem with this is it gets deleted every time the Designer.CS is regenerated by Visual Studio. So the effect is possible, just not convenient with the tools we are given.
I am new to C# and I am following this C# tutorial at the moment. In this tutorial I came across the exercise to develop a calculator.
A C# .Net Calculator - Design Stage
In the solution given in the exercise, each digit button was given a btn*_click method which can be generalized pretty easily.
(source: homeandlearn.co.uk)
How can we write the code, so that we can generalize these 10 functions? I though it can be done by modifying initializeComponent(), but comment about it says it should not be modified using code editor.
How can this problem be tackled.
You can tie all buttons to the same click event handler, and use sender to get the text:
private void btnAnyButton_Click(object sender, EventArgs e)
{
Button theButton = sender as Button;
txtDisplay.Text += theButton.Text;
}
The tutorial you posted is using the visual editor in visual studios. By default the designer will generate code with the convention {controlname}_{eventname} you can explicitly assign a different event name in the properties window, and all the buttons could share the same event method.
And then it looks like you could refactor this like:
private void btn_click(object sender, EventArgs e)
{
Button btn = sender as Button;
if(btn != null)
txtDisplay.Text += btn.Text;
}
I hope that helps.
You could generate these buttons dynamically from the code and assign them some value in the tag attribute. From there, you can hook them all up to the same event handler (we're talking about the number buttons, as in 0,1,2,3,4...). In the onClick event handler you would get the tag value of the caller and do what you have to do.
Pseudocode:
void onClick(Button caller){
int btnNb = (int) caller.Tag;
//do what you have to do
}
The tag attribute is not necessary but I find it cleaner than getting the button text and converting to an int.
In my case I have panels,but to make it clear I will use buttons in my example.
I have 5(or more) buttons and I set an event,for example - OnMouseHover, to all of the five buttons.How do I get ,which one has the mouse hovered if all the events link to one method
To capture the button where the mouse is hovered,I tried using "this",but it links to the form itself.
private void buttonX_MouseHover(object sender, EventArgs e)
{
this.Text = "Test";
}
I expected the text on the specified button where the mouse is hovered to change its text to "Test",but it happened on the form.Text only.
In my real program,I have 60 panels and I again use one method for all OnMouseHover events on any of them.How do I get the panel(or button in the example above) where the mouse is hovered?
this always refers to the class instance (the form). You need to cast the sender instead:
((Control)sender).Text = "Test";
The sender is (generally) the instance raising the event - useful when using the same handler from multiple controls.
This always is the class, in this case the form itself. The object "sender" is the magic word. If it is a button cast it back into a button. Since the object is only a reference you can make changes to the sending object.