2010-11-18 21 views
50

Supongamos que quiero pasar algunos datos adicionales cuando asigno un controlador de eventos. Considere el siguiente código:C# pasando parámetros adicionales a un controlador de eventos?

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

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

¿Qué debo hacer para obtener algunos datos en mi método evHandler?

+0

tengo una solución más habitual en esta pregunta, la primera respuesta http://stackoverflow.com/questions/14058412/passing-parameter-to-an-event-handler/14058441#14058441 –

Respuesta

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

Esta es una gran solución, pero ¿y si EventHandler ya tiene TArgs? Tal como + = new EventHandler (evHandler)? – Roast

+0

Hola @Lily, no está del todo claro lo que estás preguntando. Podría ser mejor publicar una pregunta (en lugar de un comentario) con un poco más de detalle y algún código para demostrar lo que estás tratando de hacer. – spender

+1

Gracias, esto resolvió un problema que estaba teniendo, pero soy nuevo en C# así que ¿te importaría explicar qué es esta construcción de lenguaje o darme una palabra clave a google para obtener una explicación? –

0

Bueno, el más simple Identificación del método para hacer someData una variable miembro de esta manera:

public class MyClass 
{ 
    private string _eventData; 

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

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

No estoy seguro de que es la forma mejor para hacerlo, pero realmente depende del tipo de evento, el objeto, etc.

+1

estaba pensando en esto método, sin embargo la configuración puede ser llamada varias veces con diferentes datos. Esa información debe ser única para cada controlador. –

+0

En ese caso, spender o la solución de Marc es mucho mejor – CodingGorilla

17

las variables adquirido:

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

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

O (C# 2.0 alternativos):

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

se captura variable === cierre? – Matt

+2

@Matt - sí, las variables capturadas son cierres léxicos. –

+0

Para aclarar, ¿la primera solución no es válida para C# .NET 2.0? –

2

Usted puede tratar de hacer esto:

string yourObject; 

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

Se puede crear un objeto personalizado con propiedades adicionales sobre la base de objeto:

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 los datos no se deben cambiar más después de la inicialización, también puede agregar un constructor personalizado, por ejemplo.

14

Tuve un momento difícil para resolver el ejemplo de @ spender anterior especialmente con: Object.assignHandler((sender) => evHandler(sender,someData)); porque no existe tal cosa como Object.assignHandler en el sentido literal. Así que hice un poco más de búsqueda en Google y encontré this example. La respuesta de Peter Duniho fue el que hizo clic en mi cabeza (esto no es mi trabajo):

tijeretazo

El enfoque habitual es utilizar un método anónimo con un controlador de eventos que tiene su modificación firma. Por ejemplo:

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

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

Por supuesto, usted no tiene que pasar en 172, o incluso hacer que el tercer parámetro un int. :)

/recorte

Usando ese ejemplo yo era capaz de pasar de dos a medida ComboBoxItem objetos a un Timer.Elapsed evento utilizando lambda notación:

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

y luego en él del manipulador:

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

Este no es un código nuevo de los ejemplos anteriores, pero sí demuestra h cómo interpretarlos. Espero que alguien como yo lo encuentre instructivo & útil para que no pasen horas tratando de entender el concepto como yo lo hice.

Este código funciona en mi proyecto (a excepción de una excepción no segura para subprocesos con los objetos ComboBoxItem que no creo que cambien la forma en que funciona el ejemplo). Estoy descifrando eso ahora.

0

Aquí está mi solución de una línea que pasa parámetros adicionales a un controlador de temporizador.

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

Mi pregunta que era similar fue marcado un duplicado de modo que me gustaría añadir una respuesta aquí, ya que no me deja en mi pregunta.

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); 
     } 
    } 
Cuestiones relacionadas