普通CLR事件:
事件的擁有者:即消息的發(fā)送者。事件的宿主可以在某些條件下激發(fā)它擁有的事件辰妙,事件被觸發(fā)則消息被發(fā)送蚊荣。
事件的響應(yīng)者:即消息的接收者、處理者榔至。事件接收者使用其事件處理器(EventHandler)對事件做出響應(yīng)。
事件的訂閱關(guān)系:事件的擁有者可以隨時激發(fā)事件欺劳。
普通的CLR事件通過事件訂閱將事件的發(fā)布者與事件的訂閱者緊密聯(lián)系在一起唧取,事件被觸發(fā)時,事件發(fā)布者通過事件訂閱將事件消息直接發(fā)送給事件訂閱者划提,事件訂閱者使用事件處理方法對事件的發(fā)生進(jìn)行響應(yīng)枫弟;
路由事件
路由事件是一種可以針對元素樹中的多個偵聽器而不是僅僅針對引發(fā)該事件的對象調(diào)用處理程序的事件,也就是說鹏往,觸發(fā)事件源的父級或子級如果都有對該事件的監(jiān)聽淡诗,則都能觸發(fā)事件。
路由事件與一般事件的區(qū)別在于:路由事件是一種用于元素樹的事件伊履,當(dāng)路由事件觸發(fā)后韩容,它可以向上或向下遍歷可視樹和邏輯樹,他用一種簡單而持久的方式在每個元素上觸發(fā)唐瀑,而不需要任何定制的代碼群凶。
邏輯樹和可視樹
邏輯樹:WPF界面元素的實際構(gòu)成,它是由程序在XAML中所有的UI元素組成哄辣。最顯著的特點就是由布局控件请梢、或者其他常用的控件組成。
可視化樹:可以說可視樹是邏輯樹的拓展柔滔,就是在界面上能夠看見的溢陪,布局、控件的內(nèi)部構(gòu)成情況睛廊。
簡單看個例子:
xaml代碼:
邏輯樹:
可視樹:
路由事件使用以下三種路由策略:
冒泡:調(diào)用事件源上的事件處理程序形真。然后,路由事件路由到連續(xù)的父元素超全,直到到達(dá)元素樹的根咆霜。大多數(shù)路由事件都使用冒泡路由策略。
直接:只有源元素本身才有機(jī)會調(diào)用處理程序作為響應(yīng)嘶朱。
隧道:最初蛾坯,將調(diào)用元素樹根目錄處的事件處理程序。然后疏遏,路由事件沿著路徑沿連續(xù)的子元素行進(jìn)脉课,到達(dá)作為路由事件源的節(jié)點元素(引發(fā)路由事件的元素)救军,通常隧道事件也稱為"preview"事件。
冒泡跟隧道的路由策略倘零,通常如果在開發(fā)的時候不讓其繼續(xù)沿著可視樹和邏輯樹再向上/向下傳遞時候唱遭,可以將其截斷,設(shè)置handle=true呈驶,這樣就會停止傳遞事件拷泽,終止在這個控件中。
自定義路由事件? ??
創(chuàng)建自定義路由事件大體可以分為三個步驟:
(1)聲明并注冊路由事件
(2)為路由事件添加CLR事件包裝
(3)創(chuàng)建可以激發(fā)路由事件的方法
首先是新建了一個類袖瞻,該類派生自RoutedEventArgs類司致,RoutedEventArgs類包含與路由事件相關(guān)的狀態(tài)信息和事件數(shù)據(jù),再新建了兩個屬性聋迎。
注冊定義路由事件通過RoutedEvent RegisterRoutedEvent注冊聲明脂矫。
第一個參數(shù)是為注冊路由事件的名稱,這個名稱不可以為空或者空字符串砌庄。
第二個參數(shù)是代表路由事件的策略羹唠,冒泡/隧道/直達(dá)之一。
第三個參數(shù)與第四個參數(shù)的類型均為Type娄昆。其中:第三個參數(shù)指定事件處理器的類型,第四個參數(shù)指定路由事件的宿主類型缝彬。本例中的事件處理器類型為EventHandler<DetailReportEventArgs>萌焰,所以第三個傳入?yún)?shù)為typeof(EventHandler<DetailReportEventArgs>)。路由事件的宿主為DetailReportButton?類谷浅,所以第四個傳入?yún)?shù)為typeof(DetailReportButton)扒俯。
通過add和remove去訂閱事件和取消事件,就類似與"+="和"-="一疯。
路由事件的觸發(fā)在OnClick方法中完成撼玄,方法中先實例化DetailReportEventArgs?類,得到對象args墩邀,并為args的EventPublisher與EventTime屬性賦值掌猛,這樣就創(chuàng)建了攜帶有路由事件相關(guān)信息的對象。然后調(diào)用?RaiseEvent方法把事件消息發(fā)送出去眉睹。