Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ItemsRepeater in ListBox etc #2594

Open
grokys opened this issue May 29, 2019 · 2 comments
Open

Use ItemsRepeater in ListBox etc #2594

grokys opened this issue May 29, 2019 · 2 comments

Comments

@grokys
Copy link
Member

@grokys grokys commented May 29, 2019

Our current item virtualization code has a few problems:

  1. It doesn't handle differently sized items very well (#2144)
  2. It assumes that 1 item = one scroll unit, meaning that it can't handle layouts that display multiple items per line (i.e. a wrapping panel, a grid)
  3. It doesn't handle smooth scrolling
  4. It doesn't correctly handle ListBoxItem children (#2936)

One of the main problems with supporting these scenarios is that the materialization of items due to changes in the source collection happens in the CollectionChanged event handler. Beacuse this occurs outside the layout pass, changes made here then trigger a layout pass. When that layout pass occurs, the virtualization algorithm is re-run, possibly with different constraints. This can cause the item that was scrolled to to be scrolled back out of the viewport, causing #2144. This could be worked around by storing temporary state to pass to the coming layout pass, however in some cases that layout pass will not occur meaning that the temporary state will be passed to a subsequent unrelated layout pass, causing other problems.

Another problem with creating the items in the CollectionChanged handler, is that we can potentially be doing much more materialization/dematerialization than required.

Initial attempt to fix this

My initial attempt to fix this involved moving the materialization of items to the layout pass, however the fact that we use a Panel to display the containers made this difficult: you don't know which containers need to be visible until the measure pass has completed, so I started by removing all Children from the container at the start of the measure pass and adding them back in. This unfortunately broke things because as controls are removed from Children they are also removed from the visual/logical tree, causing the focused element to lose focus among other things.

The solution to this would be to modify virtualizing panels to have a "virtual" list of children for the measure pass, which is then synchronized with the real Children on arrange, or to somehow delay visual/logical tree detachment. To me these solutions seem like a hack to get around the real problem: that Panels aren't the right solution for virtualization.

And this is just to fix point 1) above.

ItemsRepeater

UWP seem to have come to the same conclusion and have introduced Attached Layouts. This is a really powerful virtualization framework that would handle all points above, plus more, including nesting and grouping. In addition this is all MIT-licenced code with its source on GitHub.

UWP doesn't use ItemsRepeater for its list boxes, assumedly for back-compat reasons, but we don't have that problem being pre-1.0, and I think it could be used to implement a new ItemsPresenter or similar in Avalonia.

Unfortunately the code is written in C++/CX and there's a quite a lot of it, so porting may not be easy.

ItemsRepeater has now been ported to Avalonia; the next step is to rewrite ItemsPresenter to use it.

@grokys

This comment has been minimized.

Copy link
Member Author

@grokys grokys commented May 29, 2019

cc: @ahopper

@jmacato jmacato added the enhancement label Jun 9, 2019
@grokys grokys added this to To do in @grokys todos via automation Sep 28, 2019
@grokys

This comment has been minimized.

Copy link
Member Author

@grokys grokys commented Sep 28, 2019

Now that ItemsRepeater is ported from UWP, I plan to rework ItemsPresenter to be an ItemsRepeater in the 0.10 timeline. Currently #3040 is blocking that though.

@grokys grokys changed the title Rethinking Item Virtualization Use ItemsRepeater in ListBox etc Sep 28, 2019
@grokys grokys moved this from To do to Paused in @grokys todos Jan 28, 2020
@grokys grokys moved this from Paused to In progress in @grokys todos Jan 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
@grokys todos
  
In progress
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.