首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 學習筆記:路由事件 — 冒泡、隧道與附加事件機制

     編輯:關於.NET

路由事件核心概念

WPF 採用路由事件機制,事件可在視覺樹中跨層級傳遞。XAML 控制項多為組合元素(如 Button 內含 TextBlock),點擊內部元素仍能觸發外層控制項事件。

Button.Click 實作範例

public abstract class ButtonBase : ContentControl, ICommandSource
{
    public static readonly RoutedEvent ClickEvent;

    static ButtonBase()
    {
        ClickEvent = EventManager.RegisterRoutedEvent(
            "Click", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(ButtonBase));
    }

    public event RoutedEventHandler Click
    {
        add { base.AddHandler(ClickEvent, value); }
        remove { base.RemoveHandler(ClickEvent, value); }
    }
}

三種路由策略

策略傳遞方向命名慣例
Tunneling (隧道/管道)根元素 → 目標元素(向下)事件名加 Preview 前綴
Bubbling (冒泡)目標元素 → 根元素(向上)標準事件名(如 Click)
Direct (直接)僅在目標元素觸發傳統 CLR 事件模式

冒泡事件實測

<Border MouseRightButtonDown="MouseRightButtonDown">
 <StackPanel MouseRightButtonDown="MouseRightButtonDown">
  <Button MouseRightButtonDown="MouseRightButtonDown">Test</Button>
 </StackPanel>
</Border>
private void MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show((sender as FrameworkElement).Name);
}

右鍵點擊 Button,依序彈出:Button → StackPanel → Border,驗證冒泡向上傳遞。

Handled 標記與事件終止

RoutedEventArgs.Handled = true 可標記事件已處理,阻止繼續傳遞(但實際仍繼續路由,只是不再觸發處理器)。

private void MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
    MessageBox.Show(sender.GetType().Name);
    if (sender.GetType().Name == "StackPanel") e.Handled = true;
}

StackPanel 標記 Handled 後,Border 不再觸發處理器。

handledEventsToo 參數:強制處理已標記事件

public Window1()
{
    InitializeComponent();
    this.border1.AddHandler(
        Border.MouseRightButtonDownEvent,
        new MouseButtonEventHandler(MouseRightButtonDown),
        true); // handledEventsToo = true
}

即使事件被標記 Handled,仍會觸發此處理器。

隧道事件:Preview 前綴

<Border PreviewMouseRightButtonDown="MouseRightButtonDown">
 <StackPanel PreviewMouseRightButtonDown="MouseRightButtonDown">
  <Button PreviewMouseRightButtonDown="MouseRightButtonDown">Test</Button>
 </StackPanel>
</Border>

輸出順序反轉:Border → StackPanel → Button。隧道先於冒泡執行,若隧道階段標記 Handled,冒泡階段不再觸發。

附加事件:在未定義事件的元素上處理路由事件

類似附加屬性,父元素可訂閱子元素的路由事件:

<StackPanel Button.Click="Click">
 <Button>Test</Button>
 <CheckBox>Check</CheckBox>
</StackPanel>
private void Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show(e.Source.ToString()); // 輸出: System.Windows.Controls.Button:Test
}

StackPanel 雖無 Click 事件,仍能捕獲 Button 的點擊。**注意:** 任何冒泡經過的 ButtonBase 衍生類點擊都會觸發,CheckBox 同樣觸發。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved