Нечетное загруженное поведение в разметке против кода - PullRequest
2 голосов
/ 26 июня 2009

В настоящее время я очень смущен разным поведением в отношении события 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 - «Разметка» и «Делегат». Однако, если я удаляю Loaded="formHost_Loaded" из WindowsFormsHost, я не получаю ни при запуске. Очевидно, имеет смысл, почему я не получаю диалог «Разметка», но почему при этом также удаляется «Делегат»? Я полагаю, что это связано с порядком, в котором события называются (Window против его дочерних элементов), но мне сложно разобраться с этим.

Примечание: вы можете заменить WindowsFormsHost другими элементами управления, это действительно не должно иметь значения - я просто использовал его для еще нескольких тестов.

1 Ответ

0 голосов
/ 03 марта 2011

Обработчики события Loaded определяются до вызова любого из них, поскольку событие Loaded эффективно транслируется одновременно, начиная с вершины дерева. Поскольку вы добавили обработчик после того, как WPF определил, какие обработчики нужно вызывать, он игнорируется.

Это можно проверить с помощью Reflector. В частности, метод BroadcastEventHelper.BroadcastLoadedSynchronously вызовет метод BroadcastEventHelper.BroadcastEvent с перенаправленным событием LoadedEvent.

Метод BroadcastEvent собирает все объекты в визуальном дереве, которые сначала имеют обработчик события Loaded, а затем перебирает и вызывает события для этих объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...