Reputation: 549
Updated entire question to be more specific
I have a WPF application, when being loaded, it displays a circular loading indicator while another thread is getting data from server and manipulating the data.
This WPF application has an ItemsControl with about 500 items bounded to it, with more than 10 different templates. I have a template selector to determine which template to use depending on the item's property.
I have a checkbox, to show and hide certain textblocks in each item in the UI. When I check the checkbox, the UI will freeze for 10 seconds, then starts responding again with the textblocks. If I uncheck the checkbox, it will freeze for about 7 seconds, then the textblocks will disappear.
I know that I should use virtualization, but it does not work for me since each item does not have the same height. I've tried "Standard" VirtualizationMode, it is just slow when scrolling down, not usable for me, and "Recycle" won't work since the items do not have the same height.
Instead of having the UI to freeze for 7 - 10 seconds, I would like to display a loading indicator. I am not asking how to show the loading indicator when loading the app, but how to show the loading indicator when the UI is busy re-drawing.
Please advise, thanks!
Upvotes: 0
Views: 1594
Reputation: 33506
IIRC there are some, but think about it - when UI is about to render, then the drawing area is dirty and ready to be updated. Update is about to happen. If the update takes a long time (say, 3 seconds), then even if your eventhandler/viewmodel/etc reacts to the "I'm starting rendering" event, what would you like to actually do?
Show busy-indicator? Show? That's a change. It will mark the relevant area dirty, but something already is dirty, redraw is pending, and it will take long time (3s), right? So if you show/hide anything, it will show up after the rendering finishes. That is, your busy-indicator will probably show up after 3s and will immediately hide.
That's not relevant to other things of course.. when rendering starts, you can send a TCP packet, play a sound, display another window/surface with its own independent threds (so they won't wait until first rendering finishes), etc..
I think that what you really need to do is some mixture of:
usercontrol>grid>scroll>listbox>panel>[items:usercontrol>grid>listbox>panel>[items:grid>textblock]
into usercontrol>grid>listbox>scrollpanel>[items:textblock]]
and so on, that's the basics for starters.. Besides some basic points, optimizing WPF may actually be hard. Some further reading below, most of the articles I know from previous experience, helped me to successfully optimize many apps:
And now, to answer your question, though I still think that's not the right way:
event CompositionTarget.Render
MSDNDispatcherPriority.ContextIdle
MSDN ; source articleUpvotes: 3