我有一个UserControl,我希望公开一个事件:
public event RoutedEventHandler CloseButtonClicked;
但是要发送到此活动,以下不会工作:
public MyUserControl()
{
InitializeComponent();
closeButton.Click += CloseButtonClicked;
}
以下 工作:
public MyUserControl()
{
InitializeComponent();
closeButton.Click += (sender, args) => CloseButtonClicked(sender, args);
}
为什么?
答案 0 :(得分:1)
两种情况之间的差异在于评估CloseButtonClicked
事件。
在第一个非工作示例中,在执行程序语句closeButton.Click += CloseButtonClicked;
时计算事件字段的值。除非您已经将字段设置为某个有用的值,否则稍后当Click
事件被引发时,将不会发生任何事情。
在第二个工作示例中,在引发Click事件时评估事件字段的值。该语句声明了一个匿名方法(通过lambda表达式),该方法在执行时调用存储在CloseButtonClicked
事件字段中的委托实例。因此,只要在引发事件之前设置该字段,在执行closeButton.Click += (sender, args) => CloseButtonClicked(sender, args);
语句时没有设置字段就不重要了。
请注意,如果在引发CloseButtonClicked
事件时Click
事件字段尚未初始化,则即使第二个语句也会失败,并显示NullReferenceException。在引发事件时,您应该通过先检查null来防止这种情况(并且最好通过首先将值保存到本地来防止任何线程争用情况)。例如:
closeButton.Click += (sender, args)
{
RoutedEventHandler handler = CloseButtonClicked;
if (handler != null)
{
handler(sender, args);
}
};
当然,上述样板文件通常封装成辅助方法(扩展名或其他方法)。
答案 1 :(得分:0)
此行不会告诉发生closeButton.Click时要执行的内容:
closeButton.Click += CloseButtonClicked;
获取实际方法。您需要先设置CloseButtonClicked:
CloseButtonClicked += MyMethodWhichDoesSomething;
现在创建方法MyMethodWhichDoesSomething并引发一个事件(CloseButtonClicked(sender,e);)
这一行做了什么,它实际上创建了一个引发事件的方法......
closeButton.Click += (sender, args) => CloseButtonClicked(sender, args);