为什么我不能直接在c#中传递RoutedEventHandler

时间:2014-10-28 13:26:06

标签: c# events routed-events

我有一个UserControl,我希望公开一个事件:

public event RoutedEventHandler CloseButtonClicked;

但是要发送到此活动,以下不会工作:

public MyUserControl()
{
    InitializeComponent();

    closeButton.Click += CloseButtonClicked;
}

以下 工作:

public MyUserControl()
{
    InitializeComponent();

    closeButton.Click += (sender, args) => CloseButtonClicked(sender, args);
}

为什么?

2 个答案:

答案 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);