How to Know When a FrameworkElement Has Been Totally Rendered?
Asked Answered
D

2

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.

Disassembly answered 17/12, 2015 at 16:55 Comment(11)
Description for Loaded event on MSDN - Occurs when the element is laid out, rendered, and ready for interaction.Helfant
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)Disassembly
If it's ready for interaction, one could assume it's entirely rendered.Thomasina
@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.Disassembly
Show me something that returns Loaded=True but is still "waiting for the rendering pipeline" and I'll understand your point better amigo.Thomasina
@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.Disassembly
Haha oh I understand just fine, happy holidays.Thomasina
@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.Bellboy
@Bellboy Howdy, thanks I'll keep that in mind although I had long forgotten this from years ago. Cheers and have a great weekend!Thomasina
@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!Bellboy
@Bellboy I have finally found someone that actually believes in what I said. It only took four years!Disassembly
F
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!

Flypaper answered 18/12, 2015 at 21:29 Comment(2)
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.Disassembly
@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.Altricial
T
6

This worked well for me before in similar scenarios:

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

    private void DoYourThing()
    {

    }
Trey answered 18/12, 2015 at 11:15 Comment(1)
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.Bellboy

© 2022 - 2024 — McMap. All rights reserved.