我在WPF应用程序中有一个附加属性。
下面的代码位于"OnLoad"事件内,但如果我不添加500毫秒的hacky延迟,它就无法正常工作。
有没有办法避免这种延迟,并检测视觉树何时已加载?
如果您正在使用DevExpress,这甚至更为关键:在
例如:
下面的代码位于"OnLoad"事件内,但如果我不添加500毫秒的hacky延迟,它就无法正常工作。
有没有办法避免这种延迟,并检测视觉树何时已加载?
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 类对于扫描可视树的上下文非常有用。
有关扫描可视树的示例代码,请参见:
更新 3
如果您在使用附加属性,可靠地加载可视树的唯一方法是在Loaded
事件处理程序中执行代码或之后。如果我们不了解这个限制,那么所有事情都会间歇性地失败。等到OnLoaded
事件触发后再执行代码要比尝试引入其他随机延迟的任何其他方法更好,如上所述。如果您正在使用DevExpress,这甚至更为关键:在
Loaded
事件之前尝试执行任何操作,在某些情况下可能会导致崩溃。例如:
- 在
Loaded
事件之前调用window.Show()
在某些情况下会导致崩溃。 - 在
Loaded
事件之前钩入IsVisibleChanged
事件处理程序在某些情况下会导致崩溃。
声明:我与DevExpress无关,它是许多优秀的WPF库之一,我也推荐Infragistics。