我有一个已经向用户显示的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处理吗?