Pass extra parameters to an event handler?

C#EventsCallback

C# Problem Overview


Let's say I want to pass some extra data when assigning an event handler. Consider the following code:

private void setup(string someData)
{
     Object.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
    // need someData here!!!
}

How would I go about getting someData into my evHandler method?

C# Solutions


Solution 1 - C#

private void setup(string someData)
{
     Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
    // need someData here!!!
}

Solution 2 - C#

I had a hard time figuring out @spender's example above especially with: Object.assignHandler((sender) => evHandler(sender,someData)); because there's no such thing as Object.assignHandler in the literal sense. So I did a little more Googling and found this example. The answer by Peter Duniho was the one that clicked in my head (this is not my work):

> snip > The usual approach is to use an anonymous method with an event handler > that has your modified signature. For example: > > void Onbutton_click(object sender, EventArgs e, int i) { ... } > > button.Click += delegate(object sender, EventArgs e) > { Onbutton_click(sender, e, 172); }; > > >Of course, you don't have to pass in 172, or even make the third parameter >an int. :)

>/snip

Using that example I was able to pass in two custom ComboBoxItem objects to a Timer.Elapsed event using lambda notation:

simulatorTimer.Elapsed +=
(sender, e) => onTimedEvent(sender, e,
(ComboBoxItem) cbPressureSetting.SelectedItem,
(ComboBoxItem) cbTemperatureSetting.SelectedItem);

and then into it's handler:

static void onTimedEvent(object sender, EventArgs e, ComboBoxItem pressure, ComboBoxItem temperature)
    {
        Console.WriteLine("Requested pressure: {0} PSIA\nRequested temperature: {1}° C", pressure, temperature);
    }

This isn't any new code from the examples above, but it does demonstrate how to interpret them. Hopefully someone like me finds it instructive & useful so they don't spend hours trying to understand the concept like I did.

This code works in my project (except for a non-thread-safe exception with the ComboBoxItem objects that I don't believe changes how the example works). I'm figuring that out now.

Solution 3 - C#

Captured variables:

private void setup(string someData)
{
    Object.assignHandler((sender,args) => {
        evHandler(sender, someData);
    });
}

public void evHandler(Object sender, string someData)
{
    // use someData here
}

Or (C# 2.0 alternative):

    Object.assignHandler((EventHandler)delegate(object sender,EventArgs args) {
        evHandler(sender, someData);
    });

Solution 4 - C#

you can try doing this:

string yourObject;

theClassWithTheEvent.myEvent += (sender, model) =>
{
 yourObject = "somthing";
}

Solution 5 - C#

My question that was similar was marked a duplicate so thought I'd add an answer here since it won't let me on my question.

class Program
    {
        delegate void ComponentEventHandler(params dynamic[] args);

        event ComponentEventHandler onTest;

        static void Main(string[] args)
        {  
            Program prg = new Program();

            // can be bound to event and called that way
            prg.onTest += prg.Test;
            prg.onTest.Invoke("What", 5, 12.0);

            Console.ReadKey();
        }

        public void Test(params dynamic[] values)
        {
            // assign our params to variables
            string name = values[0];
            int age = values[1];
            double value = values[2];

            Console.WriteLine(name);
            Console.WriteLine(age);
            Console.WriteLine(value);
        }
    }

Solution 6 - C#

Well, the simplest method id to make someData a member variable like so:

public class MyClass
{
    private string _eventData;

    private void setup(string someData) 
    {
       _eventData = someData;
       Object.assignHandler(evHandler);
    }

    public void evHandler()
    {
        // do something with _eventData here
    }
}

I'm not sure that's the best way to do it, but it really depends on the event type, the object, etc.

Solution 7 - C#

You could create a custom object having additional properties based on Object:

class CustomObject : Object
{
	public string SomeData;
}

private void setup(string someData)
{
	CustomObject customObject = new CustomObject { SomeData = someData };
	CustomObject.assignHandler(evHandler);
}

public void evHandler(Object sender)
{
	string someData = ((CustomObject)sender).SomeData;
}

If the data should not be changed anymore after initialization, you could also add a custom constructor, for example.

Solution 8 - C#

Here is my one-line solution that pass extra parameters to a timer handler.

private void OnFailed(uint errorCode, string message)
{
    ThreadPoolTimer.CreateTimer((timer) => {
    UI.ErrorMessage = string.Format("Error: 0x{0:X} {1}", errorCode, message);
    }, System.TimeSpan.FromMilliseconds(100));
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndy HinView Question on Stackoverflow
Solution 1 - C#spenderView Answer on Stackoverflow
Solution 2 - C#delliottgView Answer on Stackoverflow
Solution 3 - C#Marc GravellView Answer on Stackoverflow
Solution 4 - C#IdanView Answer on Stackoverflow
Solution 5 - C#user441521View Answer on Stackoverflow
Solution 6 - C#CodingGorillaView Answer on Stackoverflow
Solution 7 - C#Michael GeierView Answer on Stackoverflow
Solution 8 - C#RamiusView Answer on Stackoverflow