2011-11-18 69 views
6

我有一个功能,void Validate()一个单一的事件处理程序,包含我所有的验证逻辑的窗口。实现多个控件与不同的事件处理程序委托

我不能简单地注册此作为一个事件处理程序,因为它不接受的事件处理程序委托所需的参数。另外不同类型的控件有不同的签名,所以我不能只是Validate匹配一个签名而忽略了内容。

这里是什么,我已经设置

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 
} 

这恰恰说明了两个例子,更多的控制可以有更多的签名,一个小例子。有没有更好的方法让所有的事件处理程序在我不关心传递参数的情况下调用函数?


编辑: 我喜欢乔恩提出的选项添加参数,完全无视。这的确解决了大部分问题,但只要我想直接调用这个函数,比如手动触发验证,然后我必须包括虚拟参数,以满足编译器。 ValidateOptions(this,new EventArgs())

Dan提出的使用匿名函数的建议可以处理这个问题,但在关联事件处理程序时并不那么干净。

似乎任何一种解决方案都不允许您将函数注册为事件处理函数,而忽略签名,同时还保留调用函数而不创建伪参数的功能,但有多种方法可以非常接近。


编辑:

这里是更新的例子实施乔恩对一般事件处理解决方案,但保持0参数的函数,可以直接调用

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 
} 

回答

6

可以具有忽略参数一个方法:

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

编译器将允许来自ValidateOptions方法组任何委托类型转换的正常事件模式,例如以下第一个参数是sender,第二个参数是一些类型从EventArgs的。

+0

即使签名无效'(对象,对象)'会实际工作。 –

+2

@ H.B。:真的 - 我宁愿让事情变得明显:) –

+0

@Jon我喜欢这样,它确实有效,但我后来意识到我忽略了原始问题中的部分用例(已更新) 。 Validate()函数还没有这样做的原因之一是因为我想调用它来强制从其他函数进行验证,并且通过这种方法我简化了事件处理程序的使用,但是在直接调用它时必须使用假值。 – Eric

5

您可以使用lambda表达式来减少尽管在幕后,您为包装器编写的代码量仍然在创建包装器方法来丢弃参数。

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

此处理程序提供了一个单一的回调框架控制和参数“E”被保留用于消费...

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

    } 
+0

当所有事件参数从'EventArgs'继承时,没有必要使用'dynamic',你只需要松开你在装箱时留下的小界面。 –

相关问题