What is exactly the += ( s, e ) in the code?
example:
this.currentOperation.Completed += ( s, e ) => this.CurrentOperationChanged();
This is the way to attach an event handler using Lambda expression.
For example:
button.Click += new EventHandler(delegate (Object s, EventArgs e) {
//some code
});
Can be rewritten using lambda as follows:
button.Click += (s,e) => {
//some code
};
One thing to note here. It is not necessary to write 's' and 'e'. You can use any two letters, e.g.
button.Click += (o,r) => {};
The first parameter would represent the object that fired the event and the second would hold data that can be used in the eventhandler.
This codes adds an event listener in form of a Lambda expression. s stands for sender and e are the EventArgs. Lambda for
private void Listener(object s, EventArgs e) {
}
This is an assignment of a delegate instance (the start of a lambda expression) to an event invocation list. The s, e represents the sender and EventArgs parameters of the event delegate type.
See http://msdn.microsoft.com/en-us/library/ms366768.aspx for more info.
It is a shorthand for an event handler.
s --> object sender and
e --> some type of EventArgs.
It can also be rewrriten as:
public void HandlerFunction(object sender, EventArgs e)
{
this.loaded = true;
}
Related
I am trying to understand how the lambda operator in C# is used when the given parameters are formatted in ( ), like so:
_backgroundVideoWorker.DoWork += (s, e) =>
{
outputFile = _videoEditor.JoinVideo(selectedConfiguration, videoFiles);
};
My main goal from asking this question is to understand how the different operators are being used with the lambda, += (s, e) =>.
For reference, this code excerpt is taken from an application that is joining two video files together by using the FFMPEG utility.
_backgroundVideoWorker.DoWork is an event that needs handlers.
+= indicates we are adding an event handler to handle the event.
(s, e) is saying that the expression is creating a function which accepts the s and e parameters required by the event for a function to handle it. These represent an object (s) and the DoWorkEventArgs (e). If you were to write a full function block instead of an inline lambda, they would look like (object s, DoWorkEventArgs e) or more familiarly (object sender, DoWorkEventArgs e);
BackgroudWorker.DoWork is an event with a delegate type of DoWorkEventHandler, which has the signature:
public delegate void DoWorkEventHandler(object sender, DoWorkEventArgs e)
which means that DoWork would be a function that receives two parameters, of type object and DoWorkEventArgs, respectively.
The event handler has to follow the same signature as the event's delegate, therefore, when you speficy (s, e) => { /*..*/ } as the event handler, the compiler will assume that s corresponds to the object sender parameter, while e corresponds to the DoWorkEventargs e parameter. Of course, you don't have to name them s and e
Is there a way that I am able to use 'custom' parameters with a function that is used when the value in an entry widget is changed.
the basic function is:
public void(object sender, EventArgs args){
Entry ent1 = (Entry)sender;
}
what I tried:
public void onChange(object sender, EventArgs args, String name){
Entry ent1 = (Entry)sender;
}
but It would run, because when I was calling the function it was:
entry1 += onChange("testname");
which only passes one paramter to the function, when it needs three.
What I'm asking is how can I use a 'custom' paramter like 'name', and still pass the values for 'sender' and 'args'?
You will have to create a delegate that wraps code that passes that extra parameter.
You should be able to do it with this syntax:
entry1 += (s, e) => onChange(s, e, "testname");
However, this will make you unable to unsubscribe that event. If you need that, you will have to store the delegate:
ChangeEventHandler onchange = (s, e) => onChange(s, e, "testname");
entry1 += onchange;
...
entry1 -= onchange;
I have been tinkering with Events to gain a better understanding of their use in very general situations. I'm surprised to find the following, so I'm probably heading in the wrong direction...the essence of what I'm doing is changing a button to a random color when it is clicked:
Windows Form
public Form1()
{
ColorChanges KK = new ColorChanges();
KK.ColorEventHandler += handle_ColorChanges;
button1.Click += delegate { KK.ChangeColor(button1); };
}
Event Class
class ColorChanges
{
*... properties & constructor*
public void ChangeColor(object sender)
{
*... randomly assign color to ColorEventArgs*
}
protected virtual void onColorEvent(object sender, ColorEventArgs e)
{
EventHandler<ColorEventArgs> ceh = ColorEventHandler;
{
if (ceh != null)
{
ceh(sender, e)
}
}
}
public event EventHandler<ColorEventArgs> ColorEventHandler;
}
Custom Event Args
public class ColorEventArgs : EventArgs
{
public Color xColor { get; set; }
}
Event Handler
public void handle_ColorChanges(object sender, ColorEventArgs e)
{
if (sender is Button)
{
var ButtonSender = (Button)sender;
ButtonSender.BackColor = e.xColor;
}
}
So the edited questions are:
Is use of the EventHandler(TEventArgs) Delegate useful? MS documentation indicates that syntax like
button1.Click += new EventHandler<AutoRndColorEventArgs>(handle_ColorChanges);
is correct, but that will not reach my code to randomly select a color and an error
"No overload for 'handle_ColorChanges' matches delegate >'System.EventHandler' "
so something like
button1.Click += new EventHandler<AutoRndColorEventArgs>(KK.ChangeColor(button1));
or
button1.Click += new EventHandler(KK.ChangeColor(button1));
Error says that a method is required and if I use
"No overload for 'handle_ColorChanges' matches delegate
'System.EventHandler'"
Lambda expressions help thanks for the supporting answers
button1.Click += (sender,args) => KK.ChangeColor(s);
But that doesn't allow un-assignment and that will be required later...
An anonymous delegate has the same problem
button1.Click += delegate(object sender, EventArgs e)
{ KK.ChangeColor(sender); };
The crux of the problem is that my color methods or their delegates do not match the button delegate signature (object, event). I don't care about the button args and want to use my own HOW?
Is the use of the delegate correct?
Yep, what you are doing is assigning an anonymous delegate as your event handler. This is perfectly valid, however, the catch here is you can't unassign the event handler because you have no reference to it. You could keep a reference to it and do it that way (if required)
var clickHandler = delegate { ... };
button1.Click += clickHandler;
...
button1.Click -= clickHandler
If you need access to the parameters of the event handler you will need to add those into the signature e.g.
button1.Click += delegate (object sender, EventArgs args) { ... }
The new EventHandler(SomeHandlerMethod) construct is the long way of doing things, it's synonymous to += SomeHandlerMethod. Your code currently doesn't work because you are trying to actually call the handler inside the constructor when the constructor expects a reference to the method
+= new EventHandler<ColorEventArgs>(KK.ChangeColor);
Is there a better structure for this?
Yeah, you can do it using even less code
button1.Click += (s, args) => KK.ChangeColor(button1);
This is incorrect:
button1.Click += new EventHandler<AutoRndColorEventArgs>(KK.ChangeColor(button1));
Instead of KK.ChangeColor(button1), you just need to specify the event handler method name as you did in here:
KK.ColorEventHandler += handle_ColorChanges;
The event handler method signature should match with the EventHandler delegate.If you want to just call a method in event handler, you can use lambda statement like this:
button1.Click += (s,e) => KK.ChangeColor(s);
Or:
button1.Click += delegate(object s, EventArgs e) { KK.ChangeColor(s); };
By doing this you are creating an anonymous method and attach it to your Click event.
The first one code is shorthand notation of second:
itemCountLines.Click = itemCountLines.Click + (sender, args) => countLines();
itemCountLines.Click += (sender, args) => CountLines();
But i did not understand what this expression is doing.Anybody Please Explain it to me
This code adds an handler to the Control.Click event:
public event EventHandler Click
where EventHandler is a delegate of type:
public delegate void EventHandler(
object sender,
EventArgs e
)
Normally, given you have a method with the same signature:
void SomeClickHandler(object sender, EventArgs e)
{
CountLines();
}
you would add this handler to handle Click event:
itemCountLines.Click += SomeClickHandler;
Operator += is possible because Click is an event, so you can add or remove a multiple EventHandlers to it. Simple speaking, after some control is clicked, you may want to make multiple actions (show some other control, log it to the database etc) so you are able to add multiple event handlers. You can even do itemCountLines.Click -= SomeClickHandler somewhere later to say, you do not want to handle Click with SomeClickHandler anymore.
But above code needs to define method SomeClickHandler which sometimes is unnecessary (for example, it is used only one in whole class). Then you can use anonymous delegate (added in C# 2.0):
itemCountLines.Click += delegate(object sender, EventArgs args)
{
CountLines();
};
but you can further shorten this syntax with lambda expression (added in C# 3.0) to:
itemCountLines.Click += (sender, args) => CountLines();
It simply add an event to the list of listeners itemCountLines.Click = itemCountLines.Click + (sender, args) so when an event occurs the instance of sender will be notified to raise the event inline => countLines(); as you are using lambda Expression => which will invoke countLines method
You're just attaching an event on Click, it is the same as saying
itemCountLines.Click += CountLines(sender, args);
Somewhere, there should be a method like this :
private void CountLines()
{
// Some Code There
}
private void dateTimePicker1_ValueChanged(object sender, Series myseries, int multiplier, EventArgs e)
{
if (datelimitsset == 1) {
var dt1 = dateTimePicker1.Value;
chart1.Series.Clear();
for (int i = 0; i < multiplier; i++)
{
config();
myseries.Points.AddXY(Convert.ToString(date[i]), Convert.ToDouble(array[i]));
string[] rowi = { Convert.ToString(date[i]), Convert.ToString(array[i]) };
dataGridView1.Rows.Add(rowi);
}
}
}
This is giving me the error:
No overload for 'dateTimePicker1_ValueChanged' matches delegate 'System.EventHandler'
I do not fully understand event handlers, can anyone give me advice?
The signature for System.EventHandler is (object sender, EventArgs e) so you either need to change your method signature to this:
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
Or keep your current signature and use a lambda expression as a delegate adapter when you subscribe to the event:
dateTimePicker1.ValueChanged += (object sender, EventArgs e) =>
dateTimePicker1_ValueChanged(sender, [your Series variable], [your int multiplier variable], e);
When you use a lambda expression as a delegate adapter, you are essentially creating a delegate which conforms to the System.EventHandler signature (it is passed an object and an EventArgs argument), which then calls your original handler method passing all of the arguments required to satisfy your dateTimePicker1_ValueChanged method.
The reference documentation for the System.EventHandler delegate.
EDIT: documentation for an example handler for the DateTimePicker.ValueChanged event
It's because your handler must have the same signature specified by the EventHandler delegate.
That is, you'll have to remove your two middle parameters:
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
}
In terms of a workaround for passing these parameters into the function, you have a few options...
Generate the event handler as an anonymous function (as per James' answer)
Store and retrieve them from instance variables
Store them on the DateTimePicker control's Tag property and resolve them in the handler
The second option should be obvious enough...
The third option might look like:
// In control initialization somewhere
dateTimePicker1.Tag = new DateTimePickerParams() { Series = myseries, Multiplier = multiplier }; // Where DateTimePickerParams is your own private class/struct defined explicitly for this purpose...
private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
{
var ctl = sender as DateTimePicker;
var parameters = ctl.Tag as DateTimePickerParams;
var mySeries = parameters.Series;
var multiplier = parameters.Multiplier;
// Execute...
}
You can't add arbitrary parameters to the event handler like that, the method signature must match the event delegate. How would the DateTimePicker know what to pass for the myseries and multiplier parameters?