标记与代码中的奇数加载行为

时间:2009-06-25 22:08:22

标签: wpf xaml

我目前对FrameworkElement.Loaded事件的不同行为感到困惑。我已经整理了一个演示这个的小示例应用程序。

的Xaml:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300"
        Loaded="Window_Loaded">
    <Grid>
        <TabControl>
            <TabItem Header="Tab 1" />
            <TabItem Header="Tab 2" >
                <WindowsFormsHost Name="formHost" Loaded="formHost_Loaded" />
            </TabItem>
        </TabControl>
    </Grid>
</Window>

代码:

using System.Windows;

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            formHost.Loaded += delegate
            {
                MessageBox.Show("Delegate");
            };
        }

        private void formHost_Loaded(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Markup");
        }
    }
}

实际上,当我运行应用程序时,我立即得到两个MessageBox es - “Markup”和“Delegate”。但是,如果我从Loaded="formHost_Loaded"删除了WindowsFormsHost,我就不会在启动时获取。很明显为什么我没有得到“标记”对话框,但为什么这也删除了“委托”?我认为它与事件被调用的顺序有关(Window与其子项),但我很难搞清楚它。

注意:您可以将WindowsFormsHost替换为其他控件,它确实无关紧要 - 我只是将它用于其他一些测试。

1 个答案:

答案 0 :(得分:0)

Loaded事件处理程序在调用任何事件处理程序之前确定,因为Loaded事件从树顶部开始有效地全部广播。由于您在WPF确定需要调用哪些处理程序后添加了处理程序,因此将忽略它​​。

这可以使用Reflector进行验证。具体来说,BroadcastEventHelper.BroadcastLoadedSynchronously方法将使用LoadedEvent路由事件调用BroadcastEventHelper.BroadcastEvent方法。

BroadcastEvent方法首先收集可视树中具有Loaded事件处理程序的所有对象,然后遍历并引发这些对象上的事件。