Window无法处理从后代初始化事件处理程序中引发的路由事件

时间:2015-07-02 17:37:48

标签: c# wpf xaml

我有一个已经向用户显示的MainWindow。在该窗口中有一个按钮,当单击该按钮时,将加载由包含TextBlocks的ListBox组成的UserControl。这些TextBlocks在事件处理程序中为其Initialized和Loaded事件引发路由事件(即SomeEvent)。但是,只有TextBlock.Loaded上引发的事件才会将可视树冒泡到MainWindow,而TextBlock.Initialized上引发的事件则不会。

考虑以下示例项目:

MainWindow.xaml

<Window x:Class="RoutedEventsExample.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">

    <StackPanel>
        <TextBlock x:Name="ui_mainWindowLoadStatus" />

        <StackPanel Orientation="Horizontal" Margin="0,20,0,0">
            <TextBlock Text="Items Initialized:" />
            <TextBlock x:Name="ui_initializedCount" Margin="10,0,0,0" />
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="0,20,0,0">
            <TextBlock Text="Items Loaded:" />
            <TextBlock x:Name="ui_loadedCount" Margin="10,0,0,0" />
        </StackPanel>

        <Button Click="Button_OnClick" Content="Display Items" Margin="0,20,0,0" />

        <Border x:Name="ui_host" Margin="0,20,0,0" />
    </StackPanel>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    private int m_initializedCount;
    private int m_loadedCount;

    public MainWindow()
    {
        AddHandler(SomeEvent, new RoutedEventHandler((s, e) =>
        {
            if (e.OriginalSource.ToString().Contains("Initialized"))
            {
                ui_initializedCount.Text = Convert.ToString(++m_initializedCount);
            }
            else if (e.OriginalSource.ToString().Contains("Loaded"))
            {
                ui_loadedCount.Text = Convert.ToString(++m_loadedCount);
            }
        }));

        Loaded += (s, e) => ui_mainWindowLoadStatus.Text = "MainWindow.IsLoaded = " + IsLoaded;

        InitializeComponent();
    }

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        ui_host.Child = new Items();
    }

    public static readonly RoutedEvent SomeEvent = EventManager.RegisterRoutedEvent("Some", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MainWindow));
}

Items.xaml

<UserControl x:Class="RoutedEventsExample.Items"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             xmlns:routedEventsExample="clr-namespace:RoutedEventsExample"
             mc:Ignorable="d"
             d:DesignHeight="300" d:DesignWidth="300">

    <ListBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type routedEventsExample:Items}}, Path=ItemsSource}"
             VirtualizingStackPanel.IsVirtualizing="False">
        <ListBox.ItemTemplate>
            <DataTemplate DataType="{x:Type system:String}">
                <routedEventsExample:Item />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</UserControl>

Items.xaml.cs

public partial class Items : UserControl
{
    private const int NumberOfItems = 3;

    public IEnumerable<string> ItemsSource
    {
        get
        {
            var itemsSource = new List<string>();
            for (var i = 1; i <= NumberOfItems; i++)
            {
                itemsSource.Add(Convert.ToString(i));
            }

            return itemsSource;
        }
    }

    public Items()
    {
        InitializeComponent();
    }
}

Item.xaml

<UserControl x:Class="RoutedEventsExample.Item"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:system="clr-namespace:System;assembly=mscorlib"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             d:DataContext="{d:DesignInstance system:String}">

    <TextBlock Text="{Binding}" Initialized="TextBlock_OnInitialized" Loaded="TextBlock_OnLoaded" />
</UserControl>

Item.xaml.cs

public partial class Item : UserControl
{
    public Item()
    {
        InitializeComponent();
    }

    private void TextBlock_OnInitialized(object sender, EventArgs e)
    {
        var textBlock = (TextBlock)sender;
        textBlock.RaiseEvent(new RoutedEventArgs(MainWindow.SomeEvent, "TextBlock_OnInitialized: " + textBlock.Text));
    }

    private void TextBlock_OnLoaded(object sender, RoutedEventArgs e)
    {
        var textBlock = (TextBlock)sender;
        textBlock.RaiseEvent(new RoutedEventArgs(MainWindow.SomeEvent, "TextBlock_OnLoaded: " + textBlock.Text));
    }
}

有人可以解释为什么从TextBlock的Initialized处理程序引发的“Some”事件不会被MainWindow处理,而从TextBlock的Loaded处理程序DO引发的“Some”事件会由MainWindow处理吗?

0 个答案:

没有答案