2014-10-28 78 views
0

我有一个用户控件,我想一个事件成为公众:为什么我不能直接在C#中通过RoutedEventHandler

public event RoutedEventHandler CloseButtonClicked; 

但调度此事件,以下工作:

public MyUserControl() 
{ 
    InitializeComponent(); 

    closeButton.Click += CloseButtonClicked; 
} 

虽然以下确实工作:

public MyUserControl() 
{ 
    InitializeComponent(); 

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

这是为什么?

+1

你可以显示'CloseButtonClicked'方法的声明吗? – 2014-10-28 13:29:46

+0

@EdChapel它在我的问题的第二行。 – 2014-10-28 14:07:05

+0

是否在'MyUserControl'中真正声明了'CloseButtonClicked'事件(您尝试使用它的同一个类)? – dewaffled 2014-10-28 14:26:54

回答

1

两种情况之间的区别是当CloseButtonClicked事件被评估。

在第一个非工作示例中,事件字段的值在执行程序语句closeButton.Click += CloseButtonClicked;时进行评估。除非您已经将该字段设置为某个有用的值,否则稍后在引发事件时不会发生任何事情。

在第二个工作示例中,在引发Click事件时评估事件字段的值。该语句声明了一个匿名方法(通过lambda表达式),该方法在执行时调用存储在CloseButtonClicked事件字段中的委托实例。所以只要该字段在事件发生前设置,那么在执行closeButton.Click += (sender, args) => CloseButtonClicked(sender, args);语句时设置的字段不是并不重要。

请注意,即使第二条语句也会失败,并带有NullReferenceException,如果在引发Click事件时CloseButtonClicked事件字段尚未初始化。在引发事件时,应该首先检查null(并且最好通过将值保存为本地优先级来防止任何线程竞争条件),以防止出现这种情况。例如:

closeButton.Click += (sender, args) 
{ 
    RoutedEventHandler handler = CloseButtonClicked; 

    if (handler != null) 
    { 
     handler(sender, args); 
    } 
}; 

当然,上面的样板常常被封装成辅助方法(扩展或其他方式)。

0

这行不知道什么时候会发生closeButton.Click要执行什么:

closeButton.Click += CloseButtonClicked; 

要获得实际的方法进去。您需要先设置CloseButtonClicked:

CloseButtonClicked += MyMethodWhichDoesSomething; 

现在创建方法MyMethodWhichDoesSomething并有引发事件(CloseButtonClicked(发件人,E);)

什么这行做,实际上创建了这引起了事件的方法。 ..

closeButton.Click += (sender, args) => CloseButtonClicked(sender, args); 
相关问题