作者:Junhot
更新时间:2004-12-17
-------------------------------------------------------------------------------

     上篇文章说明了控件事件是如何被Dialog触发的,那么我们如何在实际使用中利用这些控件事件呢?我们需要将事件绑定到我们自己的方法。这样,一旦控件事件被触发,我们的程序就会自动调用我们自己的方法来处理该事件。

     这样做的好处是显而易见的。试想我们要实现如下的功能:点一个按钮,清除游戏中所有的物体。一般情况下我们是怎么做的?在点按钮的时候再去判断游戏中有多少物体,然后用一个循环销毁它们?这太无聊了,让他们收到命令就自己了断多好(真是听话……)。

     所以我们可以在物体创建时,就将按钮的Click事件与该物体的销毁方法绑定,这就是事件驱动的好处啦。DirectX Sample也给我们演示了如何利用事件驱动。比如点击Toggle full screen按钮时触发全屏方法:

            // Hook the button events for when these items are clicked
            fullScreen.Click += new EventHandler(OnFullscreenClicked);


疑问:为什么这里的绑定是绑定到EventHandler类型呢?

回答:因为ButtonClick事件是EventHandler类型的啊。

疑问:为什么ButtonClick事件是EventHandler类型的呢?为什么不能用其他类型?

回答:……这不是在编写《十万个为什么》!!

我们看看上次我们列出来的Button中的代码:

public event EventHandler Click;
/// <summary>Create new button instance</summary>
protected void RaiseClickEvent(Button sender, bool wasTriggeredByUser)
{
// Discard events triggered programatically if these types of events haven't been
// enabled
if (!Parent.IsUsingNonUserEvents && !wasTriggeredByUser)
return;

if (Click != null)
Click(sender, EventArgs.Empty);
}


实际上这个EventHandler是一个delegate(委托)方法。

什么叫委托方法呢?

委托方法说白了就是方法本身什么事都不干,你调用的时候才用一个真正干活的方法去实现这个委托。

还是一头雾水……这东西说不白了……

 

我们还是用上面的代码来说明:

首先给出EventHandler的定义,这个方法是在System命名空间下的,吃白饭的方法:

    public delegate void EventHandler(Object sender, EventArgs e);

然后我们知道Button中有这样一行:

    public event EventHandler Click;


这个时候发生了什么事呢?Click就变成了这个委托的一个实现。也就是说调用Click的时候应该是有两个参数的,所以:

if (Click != null)
Click(sender, EventArgs.Empty);

这里传了两个参数给Click事件,这两个参数实际上是EventHandler定义的。

到这里都没问题。就像声明了一个类的实例然后调用这个类一样。

 

可是Click还是什么事都没有干啊?

那当然,Click只是个事件而已,真正干活的在下面:

            fullScreen.Click += new EventHandler(OnFullscreenClicked);


这就是绑定的代码。OnFullscreenClicked我们用惯了VB或者C#应该都知道,它里面是些什么内容,肯定就是实现全屏的具体代码,要不也是调用实现全屏方法的代码。

 

那么这个+=是什么意思?

Delegate委托方法是可以用+-操作来实现多重委托的,就是说吃白饭的头头只有一个,而干活的苦力可以有很多个。这里实际上就是将fullScreen这个按钮的Click委托实现又绑上了一个具体实现:OnFullscreenClicked。想想我们最开始举的例子,我们可以把多个物体的销毁都绑定到一个按钮上,利用的就是这一点。

 

也就是说一个头头(EventHandler)给下面的小头头(Click)传达任务,小头头(Click)给苦力(OnFullscreenClicked)传达任务,苦力(OnFullscreenClicked)去做任务……

这就是委托的流程,委托最后一定要绑定到一个具体的实现方法,光有任务没人去做是不行的。

 

明白这个流程后,我们知道EventHandler实际上什么事都没有做,我们完全可以一脚踹开它,自己定义一个委托方法,在Button类的代码前面加上一行:

    public delegate void MyEventHandler(Object sender, EventArgs e);

唔……多了两个字母……

然后在Button中:

        public event MyEventHandler Click;


这样Click接受的就是MyEventHandler的委托了。

最后再绑定:

            fullScreen.Click += new MyEventHandler(OnFullscreenClicked);


小头头(Click)告诉苦力(OnFullscreenClicked):这个任务是新的头头(MyEventHandler)下达的,一定要做好!

 

疑问:EventHandlerMyEventHandler有啥区别?不还是吃白饭的!?

回答:…………