Harry Harry - 2 months ago 15
C# Question

ListView flashes black on resize when large number of items inside

I have a

based control.
It's a file explorer.
property is set, first all file system items are loaded by asynchronous method (using Win32 API).
This is super fast even for large number of files. Anyway, for C:\Windows\System32 I don't see any lag.
The items are then added to my
in batches of 64, after each 64
is awaited to show what was added before the operation finishes. This again makes the whole thing way faster and more responsive.

There is however one not very fast operation: when I need an icon for a file for the first time, I have to make a system call. This call is made in getter, it's smart, it tries to use cache if available.

The loading of the view is a blink.

However when I load a huge directory (no problem, fast) - and then resize or maximize the window - I see some black flash before the control resizes.

It's like first the window resizes, the added space is painted black, then the larger
appears. It's supper annoying and like devastates my smooth experience. Is there any way to avoid this black space?

I tried to set
background to white, didn't help. I tried to set my
background to white. No joy.

When there are not many items in the
there is no black flash, but it's still not smooth enough.

So - how to prevent seeing a black background while the control is being resized?


If anyone has performance issues with ListView - here's what should be done about it:

  1. Do not execute any expensive operations on UI thread. In my case it was not exactly it, but similar. The offending code was hidden in item constructor, it tried to make some string conversions on start. Very bad idea, all expensive operations were moved to getters which solved half of the problem. The item constructor should be empty. No initial values. No initialization at all. All properties should be read via getters. This will result in executing 20 such operations per view instead of like 20000, but only if UI virtualization is used.

  2. Use MVVM pattern, so do not add items directly, create an item source and add items to the source. This would allow built-in UI virtualization which is essential where you have a large number of items. Search "UI virtualization ListView" in Google for more details. This solved the problem definitely.

  3. Think of data virtualization if populating the item source is too slow. In my case this was unnecessary. When getting ALL the data is relatively cheap - we're good. If not - we have to get only a chunk of data which is currently needed to be shown.

  4. A simpler control template could increase application performance a little bit on some low end mobile devices.

  5. If you use unmanaged code anywhere in your application, double check it, I forgot calling DestroyIcon once, and it resulted in very weird, unexpected behavior. So dispose anything disposable, destroy unused handles and such. Make triple sure it's done, I wasted countless hours on debugging such things. To be clear: unreleased resources didn't cause any performance issues, it caused other unexpected behavior like weird exceptions, disappearing icons and such. The issues seemed to come from ListView though.