c# - WPF:在附加属性中,如何等待可视化树正确加载?

标签 c# wpf .net-4.5 attached-properties visual-tree

我在 WPF 应用程序中有一个附加属性。

下面的代码在 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。

最佳答案

如果您想等待在 UI 线程中执行某些操作,请使用 Dispatcher .你怎么捕获它?那是个骗子。

How do I get the UI thread Dispatcher?

您可以使用 DispatcherPriority选择将来的时间。优先级基于 UI 事件,因此您不能说,例如,下周。但是您可以说“让我等到绑定(bind)处理完毕”,例如。

关于c# - WPF:在附加属性中,如何等待可视化树正确加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36037963/

相关文章:

visual-studio-2010 - 通过 Visual Studio 2010 以 .NET Framework 4.5 为目标

c# - .NET Standard 2.0 中的 Microsoft.AspNet.Identity 和 Microsoft.AspNet.Identity.EntityFramework

c# - 如何确定是否为变量分配了枚举中存在的值?

c# - 需要帮助开发和绑定(bind) Double <--> 转换器

c# - 带有 MVVM 和 CommandParameter 的 ListBox SelectionChanged 事件

c# - MEF 和抽象工厂

c# - UriBuilder 没有正确组合两个 URI

c# - 当一个为空时比较整数和默认比较为真

c# - 将当前事务传递给 DbCommand

wpf - 附加属性的多重绑定(bind)