ListBox and recycle container content and layout performance #17511
Unanswered
msneijders
asked this question in
Q&A
Replies: 1 comment 4 replies
-
With these changes you likely break virtualization, keeping items from being reused on scrolling properly. If you are fine going deeper into inheriting list box and redefining some function, like you already did, I would recommend going alternative approach, familiar to WPF developer with overriding containers generator. And instead of relying ItemTemplate you can override the way containers are generated in the first place. public class MyListBox : ListBox
{
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
{
// Set special recycle key for your models. This will keep a separated recycle pool for this model.
// In the same way, you can handle multiple item types, with dedicated recycle pool. Saving lots of CPU on jumping between different templates for different model types.
if (item is MyDataModel)
{
recycleKey = typeof(MyDataContainer);
return true;
}
// Fallback to default containers.
return NeedsContainer<ListBoxItem>(item, out recycleKey)
}
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
{
// This is method where containers are created, to be reused per each recycle key. Avalonia will create as many containers as needed to display one screen of items, and pool them per specific key.
if ((Type)recycleKey! == typeof(MyDataContainer))
{
return new MyDataContainer(); // If you inherit ListBox, this container should inherit ListBoxItem as well.
}
return base.CreateContainerForItemOverride(item, index, recycleKey);
}
// Two optional, but not required method, you can override to prepare container for a new item. Note, base implementation handles selection too.
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
{
base.PrepareContainerForItemOverride(container, item, index);
}
protected override void ClearContainerForItemOverride(Control container)
{
base.ClearContainerForItemOverride(container);
}
} |
Beta Was this translation helpful? Give feedback.
4 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Context: a ListBox with a non-trivial ItemTemplate (relatively heavy for layout calculations) and scrolling performance on an android device.
My observations:
It seems that the content of the recycled ListBoxItem gets removed in
VirtualizingStackPanel.RecycleElement
. This triggers layout calculations?In release mode the layout time per frame is just over 6ms (on desktop and according to devtools overlay).
My (likely naive) changes) to prevent the removing of the content so the content will only be set once per recycle:
Now in release mode the layout time per frame is just below 3ms -- cutting half of the layout time.
On a desktop machine you notice very little in difference while scrolling. But using Android on common business devices (like Zebra TC21 that I am using) the difference is very big. Going from practically not being able to scroll to scrolling very reasonably.
Questions:
Have others noticed layout often takes too much time on (medium to low end) Android devices for scrolling a ListBox decently?
And what techniques are you using to deal with that?
What caveats would my solution here have? ie. I think it could give problems if the itemtemplate has transitions defined, which could get triggered unwantedly.
Beta Was this translation helpful? Give feedback.
All reactions