У меня есть прикрепленное свойство в приложении WPF.
Код ниже находится внутри события OnLoad
, но он не работает, если я не добавлю хакерскую задержку в 500 миллисекунд.
Есть ли способ избежать этой задержки и определить, когда визуальное дерево было загружено?
private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
{
// ... snip...
Window window = GetParentWindow(dependencyObject);
// Without this delay, changing properties does nothing.
Task task = Task.Run(
async () =>
{
{
// Without this delay, changing properties does nothing.
await Task.Delay(TimeSpan.FromMilliseconds(500));
Application.Current.Dispatcher.Invoke(
() =>
{
// Set False >> True to trigger the dependency property.
window.Topmost = false;
window.Topmost = true;
});
}
});
}
Обновление 1
Согласно ответу @Will, «используйте диспетчер и выберите соответствующий приоритет». Это работает блестяще:
private static void FrameworkElement_Loaded(object sender, RoutedEventArgs e)
{
// Wrap *everything* in a Dispatcher.Invoke with an appropriately
// low priority, to defer until the visual tree has finished updating.
Application.Current.Dispatcher.Invoke(
async () =>
{
// This puts us to the back of the dispatcher queue.
await Task.Yield();
// ... snip...
Window window = GetParentWindow(dependencyObject);
window.Topmost = true;
},
// Use an appropriately low priority to defer until
// visual tree updated.
DispatcherPriority.ApplicationIdle);
}
Обновление 2
При использовании DevExpress класс LayoutTreeHelper полезен для сканирования визуального дерева вверх и вниз.
Пример кода, который имеет дело со сканированием вверх и вниз по визуальному дереву, см.:
- DevExpress: во вложенном ресурсе , как дождаться, пока мы не будем на 100 % уверены, что DevExpress закончил построение своего визуального дерева?
- DevExpress и как убедиться, что LayoutPanel всегда впереди всего остального? а>
Обновление 3
Если вы находитесь в присоединенном свойстве, единственный способ надежно загрузить визуальное дерево — выполнить код в обработчике событий Loaded
или после него. Если мы не знаем об этом ограничении, то периодически все будет давать сбои. Ожидание, пока не сработает событие OnLoaded
, намного лучше любого другого метода, который пытается ввести другие случайные формы задержек, как отмечалось выше.
Если вы используете DevExpress, это еще более важно: попытка сделать что-либо до события Loaded
может при некоторых обстоятельствах привести к сбою.
Например:
- Вызов
window.Show()
до событияLoaded
в некоторых случаях приводил к сбою. - Подключение к обработчику событий для
IsVisibleChanged
до событияLoaded
в некоторых случаях приводило к сбою.
Отказ от ответственности: я не связан с DevExpress, это одна из многих хороших библиотек WPF, я также рекомендую Infragistics.