13

For WPF there is the ContentRendered event in the Window class which let us know when the visual elements have been rendered.

Is there anything that would help me achieve the same result for UWP apps? I'd like know when a FrameworkElement has been completely rendered so I can trigger some actions after that. I don't think the Loadedevent helps on that since it's triggered way before there's anything on screen.

Roney Gomes
  • 497
  • 4
  • 13
  • 1
    Description for `Loaded` event on MSDN - *Occurs when the element is laid out, rendered, and ready for interaction.* – melya Dec 17 '15 at 16:59
  • The description I get is different and does no mention to rendering: _Occurs when a FrameworkElement has been constructed and added to the object tree, and is ready for interaction._ [(Reference)](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.loaded.aspx#) – Roney Gomes Dec 17 '15 at 17:03
  • 1
    If it's ready for interaction, one could assume it's entirely rendered. – Chris W. Dec 17 '15 at 17:11
  • 3
    @ChrisW. I don't think so. The element may be ready for being laid out, all its state is set but it's still waiting for the rendering pipeline. Also, one thing is what the documentation says, other completely different one is what you get on actual running code. – Roney Gomes Dec 17 '15 at 17:16
  • Show me something that returns Loaded=True but is still "waiting for the rendering pipeline" and I'll understand your point better amigo. – Chris W. Dec 17 '15 at 17:23
  • 1
    @ChrisW. Not a problem if you can't understand, but I made my best to be as clear as possible. Also, there's no `Loaded` property on `FrameworkElement`. – Roney Gomes Dec 17 '15 at 17:30
  • Haha oh I understand just fine, happy holidays. – Chris W. Dec 17 '15 at 17:33
  • 1
    @ChrisW.: Roney is right, you can easily proof this by adding a grid inside a pivot control, and you'll see that it will be shown in the screen after the 'Loaded' method is called, which means that the component hasn't been rendered onto the screen yet. – Bruno Mar 29 '19 at 11:25
  • @Bruno Howdy, thanks I'll keep that in mind although I had long forgotten this from years ago. Cheers and have a great weekend! – Chris W. Mar 29 '19 at 13:38
  • 1
    @ChrisW. sorry about resuscitating this topic hehehehe, but I really think that regardless of the date, if the question is still valid, it still deserves some comments! I wish you a great weekend too bro! cheers! – Bruno Mar 29 '19 at 15:10
  • 2
    @Bruno I have finally found someone that actually believes in what I said. It only took four years! – Roney Gomes Mar 30 '19 at 02:18

2 Answers2

18

I would start with Loaded. It might be better than you think.

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

The Loaded event can be used as a point to hook up event handlers on elements that come from a template, or to invoke logic that relies on the existence of child elements that are the result of an applied template. Loaded is the preferred object lifetime event for manipulating element tree structures with your app code prior to the display of XAML controls for your UI. It is also appropriate to call the VisualStateManager.GoToState method from a Loaded handler in order to set an initial view state that is defined in the template, if there's no other event that also occurs on initial layout (SizeChanged does occur on initial layout).

Depending on your use case, consider LayoutUpdated.

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

LayoutUpdated is the last object lifetime event to occur in the XAML load sequence before a control is ready for interaction. However, LayoutUpdated can also occur at run time during the object lifetime, for a variety of reasons: a property change, a window resizing, or a runtime layout request (UpdateLayout or a changed control template). The LayoutUpdated event is fired after all SizeChanged events in a layout sequence occur.

Also, there's SizeChanged you might consider.

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

SizeChanged occurs during initial layout of elements on a page, when the app first is activated, because the ActualHeight and ActualWidth values for UI elements are undefined before layout happens. They only get values during the initial layout pass and thus the SizeChanged event occurs. Thereafter, during an app's lifetime, the SizeChanged event can fire from an element again if the ActualHeight and ActualWidth values change for other reasons.

Your question really didn't give me much to work with, but regardless of your use case, I bet this will come pretty close. That being said, it's also possible that you are trying to wait until the rendering is complete. A well known solution for this is to post (in the Loaded event of the control) an action to the dispatcher, which will wait to execute until after rendering is complete. If this is what you want, try a variant of this code:

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

Best of luck!

Community
  • 1
  • 1
Jerry Nixon
  • 31,313
  • 14
  • 117
  • 233
  • 1
    Thanks for the response and sorry for the late reply (the negative feedback I got from this question demotivated me to come back to this site for a while). Anyway, your last paragraph summarizes perfectly what I wanted. For some reason, we came across a situation where Loaded was being fired although the element in question wasn't still visible on screen, and we needed to do something exactly when it could be seen. – Roney Gomes Feb 18 '16 at 23:29
  • 1
    @Jerry Nixon Amazing explanation! Thank you! Please provide an advice where to place that dispatcher. I tried to add it in the "OnLoaded" event handler, but it didn't work. I'm trying to change selected note after a GridView is rendered on the screen. – GeorgiG May 28 '20 at 13:56
6

This worked well for me before in similar scenarios:

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

    private void DoYourThing()
    {

    }
Tamás Deme
  • 2,194
  • 2
  • 13
  • 31
  • I found this to be the best approach when you really want that something happens after ALL the UI elements are loaded in the screen. – Bruno Mar 29 '19 at 12:35