2011-11-18 13 views
6

Tengo una función, void Validate(), que contiene toda mi lógica de validación para una ventana.Implementación de un único controlador de eventos para controles múltiples con diferentes delegados controladores de eventos

No puedo simplemente registrar esto como un controlador de eventos porque no acepta los parámetros requeridos por los delegados del controlador de eventos. Además, los diferentes tipos de controles tienen diferentes firmas, por lo que no puedo hacer que Validate coincida con una firma sin tener en cuenta su contenido.

Aquí es un pequeño ejemplo de lo que he configurar

txt1.TextChanged += Validate_TextChange; 
    password1.PasswordChanged += Validate_RoutedEvent; 
    txt2.TextChanged += Validate_TextChange; 

    txt3.TextChanged += Validate_TextChange; 
    password2.PasswordChanged += Validate_RoutedEvent; 
    txt4.TextChanged += Validate_TextChange; 


void Validate_RoutedEvent(object sender, RoutedEventArgs e) 
{ 
    ValidateOptions(); 
} 

void Validate_TextChange(object sender, TextChangedEventArgs e) 
{ 
    ValidateOptions(); 
} 

public void ValidateOptions() 
{ 
    //Actual validation here 
} 

Esto sólo muestra 2 ejemplos, más controles podrían tener incluso más firmas. ¿Hay alguna forma mejor de conseguir que todos los controladores de eventos invoquen una función en un caso en el que no me importan los argumentos que se pasan?


EDIT: me gusta la opción propuesta por Jon añadir los parámetros y simplemente ignorarlos. Eso soluciona la mayor parte del problema, pero cada vez que deseo llamar a esta función directamente, como para activar manualmente la validación, entonces tengo que incluir argumentos ficticios para satisfacer al compilador. ValidateOptions (esto, nuevos EventArgs())

La sugerencia que Dan hizo, para usar funciones anónimas, manejaría esto pero no está tan limpio cuando se asocian los controladores de eventos.

No parece que ninguna solución le permita registrar una función como controlador de eventos mientras ignora la firma y al mismo tiempo conserva la capacidad de invocar la función sin crear argumentos ficticios, pero hay muchas maneras de acercarse mucho.


EDIT:

Aquí está el ejemplo actualizado implementación de la solución de Jon como el manejo de eventos genéricos, pero manteniendo una función 0 parámetro que se puede llamar directamente

txt1.TextChanged += ValidationEvent; 
password1.PasswordChanged += ValidationEvent; 
txt2.TextChanged += ValidationEvent; 

txt3.TextChanged += ValidationEvent; 
password2.PasswordChanged += ValidationEvent; 
txt4.TextChanged += ValidationEvent; 


//Single event handler accepting EventArgs, which is the base class 
//for all more-specific event classes 
void ValidationEvent(object sender, EventArgs e) 
{ 
    //Ignores arguments and calls 0 argument ValidateOptions 
    ValidateOptions(); 
} 

//0 argument function that performs actual validation and can be called 
//directly from other functions without the need to pass in a fake sender 
//and eventargs parameter 
public void ValidateOptions() 
{ 
    //Actual validation here 
} 

Respuesta

6

Usted puede tener un único método que ignora los parámetros:

public void ValidateOptions(object sender, EventArgs e) 
{ 
} 

El compilador permitan una conversión del grupo ValidateOptions método para cualquier tipo delegado siguiendo el patrón evento normal tales que el primer parámetro es sender y el segundo parámetro es algún tipo derivado de EventArgs.

+0

Incluso la firma 'void (objeto, objeto)' funcionaría en realidad. –

+2

@ H.B.: Es cierto - Prefiero hacer que sea obvio que está ahí para el manejo de eventos :) –

+0

@Jon Me gusta esto, y funcionó, pero luego me di cuenta de que olvidé parte del caso de uso en mi pregunta original (actualizado) . Una de las razones por las que la función Validate() aún no lo hizo es porque quería llamarlo para forzar la validación de otras funciones y con este enfoque simplifico el uso del controlador de eventos pero tengo que usar valores falsos cuando lo llamo directamente. – Eric

5

Puede usar expresiones lambda para reducir la cantidad de código que escribe para los contenedores, sin embargo, detrás de las escenas, sigue creando métodos de envoltura para descartar los parámetros.

txt3.TextChanged += (s,e) => ValidateOptions(); 
password2.PasswordChanged += (s,e) => ValidateOptions(); 
txt4.TextChanged += (s,e) => ValidateOptions(); 
0

Este controlador proporciona una única llamada de retorno para los controles de marco y el argumento 'e' se conserva para el consumo ...

private static void EventHandlerSink(object sender, dynamic e) 
    { 

    } 
+0

No es necesario utilizar 'dynamic' cuando todos los argumentos de evento heredan de' EventArgs', simplemente pierdes la pequeña interfaz que te quedaba cuando la encasillaste a eso. –

Cuestiones relacionadas