WPF學習02:Routed Events


  與傳統的桌面開發相比,在事件模型上WPF引入了Routed Events,從開發者的角度上,我們獲得了兩個便利:

  1.可以實現事件路由,即向XAML結構中的父元素路由或者是向子元素路由。

      2. RoutedEventArgs作為默認的事件Args為我們提供了更多的信息。

 

事件應用示例

  建立工程“RoutedEvent”,初始的代碼修改Grid Layout為StackPanel,添加了一個Button,如下圖:

   

  編寫Click Event Handler:

 private void ButtonA_Click(object sender, RoutedEventArgs e)
 {
     System.Diagnostics.Debug.WriteLine("Get it");
 }

   我們有兩種方式為該按鈕添加Click Event Handler:

  XAML形式:

 <Button Name="ButtonA" Click="ButtonA_Click">ButtonA</Button>

 

   C#形式:

 ButtonA.AddHandler(Button.ClickEvent, new RoutedEventHandler(ButtonA_Click)); 
 ButtonA.Click += ButtonA_Click;  //這樣亦可,但只能用於該控件支持的事件

 

 

  結果:

  

  注意:一個事件,同一個handler添加多次的結果如下圖,是引發Bug的誘因之一:

  

  

RoutedEventArgs

  從上一個例子我們可以看到,WPF事件機制默認提供的EventArgs為RoutedEventArgs

 public delegate void RoutedEventHandler(object sender, RoutedEventArgs e);

 

  與EventArgs相比,Routed Event提供了4個新的屬性.

  RoutedEvent:可以獲取到時間的類型,可以在一個Handler處理多個不同類型事件時用上。

  其它三個都與事件路由相關:

  Handled,指定sender是否對該事件繼續路由,接下來的例子會展示它的作用。

  Source,該事件的觸發源。

  OriginalSource,通常與Source為同一個值。

  

事件路由

  以事件路由模式來分類,WPF提供了3種事件路由模式:

  1. Direct (不路由)
  2. Bubbling events(向上路由)
  3. Tunneling events(向下路由)

  對於一個事件,如果不清楚它的路由模式,可以MSDN查一下:比如:MSDN上關於Click的說明:

  

  直接以例子來說明事件路由的作用:我們修改一下XAML代碼,如下:

 <StackPanel>
        <Button Name="ButtonA">ButtonA</Button>
        <Button Name="ButtonB">ButtonB</Button>
        <Button Name="ButtonC">ButtonC</Button>
        <Button Name="ButtonD">ButtonD</Button>
        <Button Name="ButtonE">ButtonE</Button>
        <Button Name="ButtonF">ButtonF</Button>
        <Button Name="ButtonG">ButtonG</Button>
        <Button Name="ButtonH">ButtonH</Button>
 </StackPanel>

 

  現在界面上有了8個Button,如果需要為8個按鈕都做事件處理,那要怎么做呢?通過事件路由我們可以很優雅的解決:

  由於Click為向上路由的事件,我們隨便找它的一個父元素,比如stackPanel,填加一句代碼就好了:

 <StackPanel Button.Click="Button_Click">

 

  以下為Handler代碼:

private void Button_Click(object sender, RoutedEventArgs e)
{
    System.Diagnostics.Debug.WriteLine("Get Info From {0}", e.Source);
}

 

  結果:

  

  為頂層Window添加同樣的代碼會得到相同的結果,因為事件將一直路由到頂層。

 

  最后,回顧一下剛才RoutedEventArgs中的Handled.

  接下來的例子說明了如何通過設置Handled阻礙事件路由:

  XAML代碼:

 <Window x:Class="RoutedEvent.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Button.Click="Button_Click">
    <StackPanel Name="StackPanelA">
        <Button Name="ButtonA">ButtonA</Button>
        <Button Name="ButtonB">ButtonB</Button>
        <Button Name="ButtonC">ButtonC</Button>
        <Button Name="ButtonD">ButtonD</Button>
        <Button Name="ButtonE">ButtonE</Button>
        <Button Name="ButtonF">ButtonF</Button>
        <Button Name="ButtonG">ButtonG</Button>
        <Button Name="ButtonH">ButtonH</Button>
    </StackPanel>
 </Window>

 

  C#代碼:

  

 public MainWindow()
 {
     InitializeComponent();
     StackPanelA.AddHandler(Button.ClickEvent, new RoutedEventHandler(StackPanel_Click), true);
 }
        
 private void Button_Click(object sender, RoutedEventArgs e)
 {
     System.Diagnostics.Debug.WriteLine("Get Info From {0}", e.Source);
 }

 private void StackPanel_Click(object sender, RoutedEventArgs e)
 {
    System.Diagnostics.Debug.WriteLine("I will block the routing", e.Source);
    e.Handled = true;
 }

 

  結果:事件路由將到了StackPanel即被阻礙,Window的對於Click 的Handler將不會觸發,大家可以試試。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM