【问题标题】:How to Know When a FrameworkElement Has Been Totally Rendered?如何知道 FrameworkElement 何时已完全渲染?
【发布时间】:2016-03-24 05:58:11
【问题描述】:

对于 WPF,Window 类中的 ContentRendered 事件让我们知道视觉元素何时呈现。

有什么可以帮助我为 UWP 应用程序实现相同的结果吗?我想知道FrameworkElement 何时完全呈现,以便在那之后触发一些操作。我不认为Loadedevent 对此有帮助,因为它是在屏幕上没有任何内容之前触发的。

【问题讨论】:

  • MSDN 上Loaded 事件的描述 - 在元素布局、呈现并准备好交互时发生。
  • 如果它已准备好进行交互,则可以假定它已完全渲染。
  • @ChrisW。我不这么认为。元素可能已准备好进行布局,其所有状态均已设置,但仍在等待渲染管道。此外,一件事是文档所说的,另一件事完全不同的是你在实际运行的代码上得到的。
  • @ChrisW。如果您无法理解,这不是问题,但是我已尽力使您尽可能清楚。此外,FrameworkElement 上没有 Loaded 属性。
  • @ChrisW.:Roney 是对的,您可以通过在枢轴控件中添加一个网格来轻松证明这一点,您会看到它会在“加载”方法后显示在屏幕上调用,这意味着组件还没有被渲染到屏幕上。

标签: c# xaml winrt-xaml uwp


【解决方案1】:

我会从 Loaded 开始。它可能比你想象的要好。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.loaded

Loaded 事件可用作连接来自模板的元素的事件处理程序的点,或调用依赖于作为应用模板结果的子元素的存在的逻辑。 Loaded 是首选的对象生命周期事件,用于在显示 UI 的 XAML 控件之前使用应用程序代码操作元素树结构。如果在初始布局上也没有发生其他事件(SizeChanged 确实在初始布局上发生),则还可以从 Loaded 处理程序调用 VisualStateManager.GoToState 方法以设置模板中定义的初始视图状态。

根据您的用例,考虑 LayoutUpdated。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.layoutupdated

LayoutUpdated 是控件准备好进行交互之前在 XAML 加载序列中发生的最后一个对象生存期事件。但是,LayoutUpdated 也可以在对象生命周期的运行时发生,原因有很多:属性更改、窗口大小调整或运行时布局请求(UpdateLayout 或更改的控件模板)。 LayoutUpdated 事件在布局序列中的所有 SizeChanged 事件发生后触发。

此外,您还可以考虑 SizeChanged。

https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.sizechanged

SizeChanged 发生在页面上元素的初始布局期间,即首次激活应用程序时,因为 UI 元素的 ActualHeight 和 ActualWidth 值在布局发生之前未定义。它们仅在初始布局传递期间获取值,因此会发生 SizeChanged 事件。此后,在应用程序的生命周期内,如果 ActualHeight 和 ActualWidth 值因其他原因发生变化,SizeChanged 事件可能会再次从元素触发。

您的问题确实没有给我太多帮助,但无论您的用例如何,我敢打赌这将非常接近。话虽如此,您也可能试图等到渲染完成。一个众所周知的解决方案是(在控件的 Loaded 事件中)向调度程序发布一个动作,该调度程序将等待执行,直到渲染完成。如果这是您想要的,请尝试以下代码的变体:

Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);

祝你好运!

【讨论】:

  • 感谢您的回复,并对迟到的回复感到抱歉(我从这个问题得到的负面反馈让我有一段时间没有回到这个网站的动力)。无论如何,你的最后一段完美地总结了我想要的。出于某种原因,我们遇到了 Loaded 被触发的情况,尽管有问题的元素在屏幕上仍然不可见,我们需要在它可以看到的时候做一些事情。
  • @Jerry Nixon 惊人的解释!谢谢!请提供建议将该调度员放置在何处。我试图将它添加到“OnLoaded”事件处理程序中,但它不起作用。我正在尝试在屏幕上呈现 GridView 后更改选定的注释。
【解决方案2】:

这对我之前在类似情况下效果很好:

    ...
    await Dispatcher.RunAsync(CoreDispatcherPriority.Low, DoYourThing);
    ...

    private void DoYourThing()
    {

    }

【讨论】:

  • 当您真的希望在所有 UI 元素都加载到屏幕后发生某些事情时,我发现这是最好的方法。
猜你喜欢
  • 1970-01-01
  • 2021-05-14
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多