2010年7月29日 星期四

WPF 學習:EventRouting

這次學到的是 WPF 的 EventRouting

有一個 Window,xaml 如下

<Window x:Class="WpfApplication1.MainForm"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainForm" Height="300" Width="300" >
    <Grid>
        <StackPanel Name="MyPanel"></StackPanel>
    </Grid>
</Window>

而 code 如下。

public MainForm()
{
    InitializeComponent();

    for (int i = 0; i < 5; i++)
    {
        var button = new Button() {Content = "Button " + i};
        MyPanel.Children.Add(button);
        button.Click += new RoutedEventHandler(button_Click);
    }
}

void button_Click(object sender, RoutedEventArgs e)
{
    var button = sender as Button;
    MessageBox.Show(button.Content.ToString());
}

執行時,會產生5個 button。每一個 button 被Click 後,會拋出所click 的按鍵訊息。

這樣的寫作方式與以前的 windows form 並沒有什麼兩樣。每個 button 的 click event 都註冊了相同的 event handler,似乎有點笨。

Event Bubbling

由於 event bubbling 的關係,button 的也會傳到其 Parent Container,在這個例子是名為 MyPanel 的 StackPanel。因此理論上MyPanel 可以收的到 Click Event.

問題來了,StackPanel 並沒有 Click Event,因此無法註冊 EventHandler. 如下圖。

image

RountEvent

雖然 MyPanel 無法直接註冊 Click Event, 但在 WPF 中由於 DependecyProperty 的幫助,我們可以使用 MyPanel.AddHandler方法的協助來註冊 Button 的 Click Event 的 Event Handler

public MainForm()
{
    InitializeComponent();

    for (int i = 0; i < 5; i++)
    {
        var button = new Button() {Content = "Button " + i};
        MyPanel.Children.Add(button);
        //button.Click += new RoutedEventHandler(button_Click);
    }
    MyPanel.AddHandler(Button.ClickEvent, new RoutedEventHandler(button_Click));            
}

void button_Click(object sender, RoutedEventArgs e)
{
    var button = e.Source as Button; //我也改了這一行
    MessageBox.Show(button.Content.ToString());
}
注意到我改了 e.Source。e.Source 是指真正發生 Event 的物件,即 Button。而sender 會指到 MyPanel,並不是我們想要的。

沒有留言:

Share with Facebook