2012-02-16 53 views
1

根據this MSDN article(等等),爲什麼在實例處理程序之前不會將此類處理程序附加到隧道事件?

類處理程序之前任何實例偵聽處理程序 附加到那個類,每當路由事件 到達在其路由中元素實例的一個實例被調用。

我是很新的RoutedEvent這麼有機會的話,我在我的代碼有錯誤,但它好像附着於被聲明爲RoutingStrategy.Tunnel一個RoutedEvent類處理程序總是在實例處理程序附加到同一事件之前觸發。

在我的例子中,我創建了一個TouchButton控制類,其中有一個隧道RoutedEvent和冒泡RoutedEvent。我爲每個註冊了類處理程序。然後我在窗口中創建了一個類的實例,並在後面的代碼中處理每個事件。我在類元素和包含它的Grid上爲隧道事件附加了相同的處理程序。所有四個處理程序在MessageBox中顯示其名稱,以便您可以清楚地看到執行順序。

  1. 網格實例PreviewTouch
  2. 類TouchButton_PreviewTouch
  3. TouchButton實例PreviewTouch
  4. 類TouchButton_Touch
  5. TouchButton實例觸摸

這意味着,如果我叫e.Handled = true;在類PreviewTouch事件處理程序,我可以停止執行所有其他的事情r事件處理程序除了附加到Grid元素之外的事件處理程序。這應該是這樣,還是我在某個地方犯了錯誤?否則,我怎樣才能停止執行每個實例事件處理程序?

這裏是類:

public class TouchButton : Button 
{ 
    static TouchButton() 
    { 
     EventManager.RegisterClassHandler(typeof(TouchButton), PreviewTouchEvent, 
new RoutedEventHandler(TouchButton_PreviewTouch), true); 
     EventManager.RegisterClassHandler(typeof(TouchButton), TouchEvent, 
new RoutedEventHandler(TouchButton_Touch), true); 
    } 

    private static void TouchButton_PreviewTouch(object sender, RoutedEventArgs e) 
    { 
     MessageBox.Show("Class TouchButton_PreviewTouch"); 
    } 

    private static void TouchButton_Touch(object sender, RoutedEventArgs e) 
    { 
     MessageBox.Show("Class TouchButton_Touch"); 
    } 

    public static RoutedEvent TouchEvent = EventManager.RegisterRoutedEvent("Touch", 
RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TouchButton)); 

    public event RoutedEventHandler Touch 
    { 
     add { AddHandler(TouchEvent, value); } 
     remove { RemoveHandler(TouchEvent, value); } 
    } 

    public static RoutedEvent PreviewTouchEvent = EventManager.RegisterRoutedEvent(
"PreviewTouch", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), 
typeof(TouchButton)); 

    public event RoutedEventHandler PreviewTouch 
    { 
     add { AddHandler(PreviewTouchEvent, value); } 
     remove { RemoveHandler(PreviewTouchEvent, value); } 
    } 

    protected override void OnClick() 
    { 
     RaiseTouchEvent(); 
    } 

    private void RaiseTouchEvent() 
    { 
     RoutedEventArgs touchEventArgs = new RoutedEventArgs(PreviewTouchEvent); 
     RaiseEvent(touchEventArgs); 
     if (!touchEventArgs.Handled) RaiseEvent(new RoutedEventArgs(TouchEvent)); 
    } 
} 

這裏是在後面的窗口代碼實例句柄:

private void TouchButton_PreviewTouch(object sender, RoutedEventArgs e) 
{ 
    MessageBox.Show(string.Format("{0} Instance PreviewTouch", 
((FrameworkElement)sender).Name)); 
} 

private void TouchButton_Touch(object sender, RoutedEventArgs e) 
{ 
    MessageBox.Show(string.Format("{0} Instance Touch", 
((FrameworkElement)sender).Name)); 
} 

這裏是控制XAML:

<Grid Name="Grid" Controls:TouchButton.PreviewTouch="TouchButton_PreviewTouch"> 
    <Controls:TouchButton x:Name="TouchButton" Width="200" Height="45" FontSize="24" 
Content="Touch me" Touch="TouchButton_Touch" PreviewTouch="TouchButton_PreviewTouch" /> 
</Grid> 

我明白隧道事件由Grid元素在'隧道化'到之前處理元素,但我認爲類處理程序總是應該在實例處理程序之前觸發。如果不是,我該如何做到這一點?

UPDATE >>>

感謝@樂觀的答案,我設法找到一種方法來阻止所有的實例句柄從處理事件。如果不是與Grid的樂觀建議更換的TouchButton聲明類處理類型,我FrameworkElement替換它,然後它會捕捉所有FrameworkElement來源的控制。

EventManager.RegisterClassHandler(typeof(FrameworkElement), PreviewTouchEvent, 
new RoutedEventHandler(TouchButton_PreviewTouch), true); 
+0

不錯的問題... – sanguine 2012-02-17 10:46:34

回答

0

MSDN文章指 - 當一個橫動事件認定其具有規定兩個類和實例處理程序然後它調用類處理程序實例處理程序之前的元素(在樹)。因此,在這種情況下,當事件被觸發並從外部傳輸到內部時,它遇到了網格,但是Grid類沒有任何類處理程序,因此它只是調用「網格」實例使用的實例處理程序。如果該行是在肘節添加按鈕 -

EventManager.RegisterClassHandler(typeof運算(網格),PreviewTouchEvent, 新RoutedEventHandler(TouchButton_PreviewTouch),TRUE);

然後Grid的實例處理程序之前,相應的級處理器將被調用。

+0

嗨,謝謝你的迴應。它沒有完全回答我的問題,但它幫助我自己回答,所以我會給你這個。 :) – Sheridan 2012-02-17 21:22:05

相關問題