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?
private void setup(string someData)
{
Object.assignHandler((sender) => evHandler(sender,someData));
}
public void evHandler(Object sender, string someData)
{
// need someData here!!!
}
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.
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);
});
vous pouvez essayer de faire ceci:
string yourObject;
theClassWithTheEvent.myEvent += (sender, model) =>
{
yourObject = "somthing";
}
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);
}
}
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.
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.
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));
}