web-dev-qa-db-fra.com

C # transmettre des paramètres supplémentaires à un gestionnaire d'événements?

Disons que je souhaite transmettre des données supplémentaires lors de l'attribution d'un gestionnaire d'événements. Considérez le code suivant:

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

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

Comment pourrais-je obtenir des données dans ma méthode evHandler?

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

J'ai eu du mal à comprendre l'exemple de @ spender ci-dessus, en particulier avec: Object.assignHandler((sender) => evHandler(sender,someData)); car il n'y a rien de tel que Object.assignHandler au sens littéral. J'ai donc fait un peu plus de recherche sur Google et trouvé cet exemple . La réponse de Peter Duniho est celle qui a cliqué dans ma tête (ce n'est pas mon travail):

couper

L'approche habituelle consiste à utiliser une méthode anonyme avec un gestionnaire d'événements qui a votre signature modifiée. Par exemple:

void Onbutton_click(object sender, EventArgs e, int i) { ... }

button.Click += delegate(object sender, EventArgs e) 
{ Onbutton_click(sender, e, 172); };

Bien sûr, vous n'avez pas besoin de passer en 172, ni même de faire du troisième paramètre un entier. :)

/ snip

En utilisant cet exemple, j'ai pu passer deux objets ComboBoxItem personnalisés à un Timer.Elapsed événement utilisant la notation lambda:

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

puis dans son gestionnaire:

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

Ce n'est pas un nouveau code des exemples ci-dessus, mais il montre comment les interpréter. J'espère que quelqu'un comme moi le trouve instructif et utile afin de ne pas passer des heures à essayer de comprendre le concept comme je l'ai fait.

Ce code fonctionne dans mon projet (à l'exception d'une exception non thread-safe avec les objets ComboBoxItem qui, à mon avis, ne change pas le fonctionnement de l'exemple). Je le comprends maintenant.

22
delliottg

Variables capturées:

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

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

Ou (alternative C # 2.0):

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

vous pouvez essayer de faire ceci:

string yourObject;

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

Ma question qui était similaire a été marquée en double, alors j'ai pensé ajouter une réponse ici car elle ne me laissera pas sur ma 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);
        }
    }
1
user441521

Vous pouvez créer un objet personnalisé ayant des propriétés supplémentaires basées sur 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;
}

Si les données ne doivent plus être modifiées après l'initialisation, vous pouvez également ajouter un constructeur personnalisé, par exemple.

0
Michael Geier

Eh bien, l'id de la méthode la plus simple pour faire de someData une variable membre comme ceci:

public class MyClass
{
    private string _eventData;

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

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

Je ne suis pas sûr que ce soit la façon la meilleure de le faire, mais cela dépend vraiment du type d'événement, de l'objet, etc.

0
CodingGorilla

Voici ma solution en ligne qui transmet des paramètres supplémentaires à un gestionnaire de temporisation.

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));
}
0
Ramius