-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Refactor ItemsControl container generation and implement smooth virtualization #9677
Conversation
A lot still broken, in particular virtualization is completely removed.`ItemsPresenter` now no longer has an `Items` or `ItemTemplate` property; it detects when it's hosted in an `ItemsControl`. `IItemsPresenter` interface removed.
Currently only supports smooth scrolling.
If you want a different virtualization mode, use a different panel.
A bunch of tests still failing, and some code commented out, but outlines the new API shape.
`ListBox` now needs a root as it uses a `VirtualizingStackPanel`.
Use a slightly different approach to the one that was previously there: create an item template that contains `DisplayMemberBinding`. This is the approach that WPF broadly uses too.
When `ItemsControl.DisplayMemberBinding` or `ItemTemplate` changes, refresh the containers.
As `DisplayMemberBinding` should select the member for the header (in WPF it's `DisplayMemberPath`). Also set `TabItem.TabStripPlacement`.
Wasn't finding `RelativeSource` type at times.
…0618_ItemContainerGenerator fix: ItemContainerGenerator obsolete member after #9677
@grokys Hi, I noticed that after migrating to preview5, ListBox no longer wraps items in container. Is this an expected behavior? |
May I ask if there is some initiative to change it to higher precision, so virtualised panels with many elements (in millions) have no offset scattering at all? I think I found a way around it, but the implementation is quite difficult and not very nice, so before I spend much time with it I would like to know, if there is not tendency to (re)implement it in some of the coming releases. Thanks |
No, none as for now.
Worth to create a new enhancement issue with details. |
My solution is probably not generally applicable so I will describe it there, and if someone find that approach acceptable to be part of framework, he can create proper issue for it. For now I will describe it here. Basically I kind of overlapped virtualised ItemsControl positioned inside Panel with my own Control (StackPanel of elements of same type and style as ItemTemplate in ItemsControl and that one is replaced with just dummy Decorator with specific Height), so ItemsControl works basically just as positioning calculator (seems like positioning is calculated properly, just render positions are scattered), and those position changes are delegated to my own overlapped StackPanel.
I find it not very elegant way of doing ui (overlapping dummy controls), but at the end it works kind of well from user's perspective (at least in my simple use-case). But more elegant way may probably be to kind of extract virtualized positioning algorithm and omit rendering capability from ItemsControl and kind of bind it to something like described above. (did not dive deeply into how virtualisation is currently done) Hope I describe it understandably. I would provide minimal repro sample, but I have kind of too bloated project and not enough time to scrape it atm. Here is also video how it works compared to default positioning: [full video] |
@GabrielHalvonik a feature request doesn't mean you need to provide a pull request, even if for sure pull requests are welcome. If the issue is kept here, it will be lost. It would be really nice if you can transfer your idea into a new issue as a feature request. To your approach in general: I wonder if it would be possible to implement an own Happy coding |
I still think it's not wise to discuss it in a merged PR. |
Yes, please open an issue to discuss this; please don't try to fix it before its discussed as there are various different ways in which this could be fixed and we need to decide where to fix it first. |
What does the pull request do?
This PR refactors item container generation for
ItemsControl
as discussed in #9497 to be more similar to the WPF/UWP model. Given that this required a major refactoring of our virtualization logic, I also rewroteVirtualizingStackPanel
to use "smooth" virtualization based on the code fromTreeDataGrid
. Now allListBox
es etc use smooth virtualization and handle variable-sized items by default. There should now no longer be a problem with using virtualization in combination with with inline items (#4265 and others).XCjM39nCrh.mp4
The main changes from the point of view of a regular consumer of
ItemsControl
-related controls are:ListBox.VirtualizationMode
has been removed, the virtualization mode is changed by changing theItemsPanel
Carousel.IsVirtualizing
has been removed, there is now only a "virtualizing" panelStackPanel
should be used if no virtualization is requiredVirtualizingStackPanel
should be used if "smooth" virtualization is requiredItemsControl
as in UWP (old methods are left onItemContainerGenerator
marked with[Obsolete]
):ItemsControl.ContainerFromIndex(object item)
ItemsControl.IndexFromContainer(Control container)
The main changes from the point of view of a virtualizing panel author are:
ItemsPresenter
is no longer responsible for generating containers, the responsibility is moved toVirtualizingPanel
ItemContainerGenerator
should no longer be inherited to modify the container type for anItemsControl
, instead override methods onItemsControl
A more detailed list of changes is listed in the Breaking Changes section.
Now the procedure to create a virtualizing panel is as follows:
VirtualizingPanel
and implement the abstract membersItemContainerGenerator
fromVirtualizingPanel
:ItemContainerGenerator.IsItemItsOwnContainer(Control)
should first be called if the item is derived from theControl
class. If this method returns true then theitem itself should be used as the container.
IsItemItsOwnContainer(Control) returns false then
ItemContainerGenerator.CreateContainer()` should be called to create a new container.VirtualizingPanel.AddInternalChild(Control)
ItemContainerGenerator.ItemContainerPrepared(Control, object?, int)
should be called.ItemContainerGenerator.ItemContainerIndexChanged(Control container, int oldIndex, int newIndex)
should be calledClearItemContainer(Control)
should be called if returned false.VirtualizingPanel
-derived class.ItemContainerGenerator
DOES NOT store the realized containers anywhere, unlike WPF/UWPVirtualizingPanel.ContainerFromIndex
andVirtualizingPanel.IndexFromContainer
should be implemented to query this collection of realized containersVirtualizingPanel
-derived class is also responsible for storing its own list of recyclcable containers and using these when necessaryIn addition, this PR finally fixes one of our oldest issues (#54):
ItemsControl
now exposes anItemsView
property which represents theItems
wrapped in anItemsSourceView
.Breaking Changes
ItemsControl
Item container generation/lifecycle API was changed to be similar to WPF/UWP.
ItemContainerGenerator
to change the container typeItemContainerGenerator
cannot be overridden from user code any moreTreeView
creates aTreeItemContainerGenerator
for backwards compatItemsControl.IsItemItsOwnContainerOverride
ItemsControl.PrepareContainerForItemOverride
ItemsControl.PrepareContainerForItemOverride
ItemsControl.ContainerIndexChangedOverride
ItemsControl.ClearContainerForItemOverride
Item container lookup was moved to
ItemsControl
as in UWP (old methods are left onItemContainerGenerator
marked with[Obsolete]
)ItemsControl.ContainerFromIndex(object item)
ItemsControl.ContainerFromItem(object item)
ItemsControl.IndexFromContainer(Control container)
ItemsControl.ItemFromContainer(Control container)
ItemContainerGenerator
IsItemItsOwnContainer
CreateContainer
PrepareItemContainer
ItemContainerPrepared
ItemContainerIndexChanged
ClearItemContainer
ItemContainerGenerator<T>
and move creation of containers to protected methods inItemsControl
(above)ItemsControl
are forwarded to theVirtualizingPanel
IItemContainerGenerator
ItemContainerInfo
ItemContainerGenerator.Containers
is nowItemsControl.GetRealizedContainers()
ItemContainerGenerator.ContainerFromIndex
andItemContainerGenerator.IndexFromContainer
, which now just call relevant methods onItemsControl
Questions
ItemFromContainer
returnsUnsetValue
if the container was not found, in UWP it unhelpfully returnsSystem.__ComObject
. Not a big fan of either of these. Currently it's implemented here as returningnull
butnull
is actually a valid item. Should we change this method tobool TryGetItemFromContainer(out object? item)
?ItemContainerGenerator
events are replaced byItemsControl.PrepareContainerForItemOverride
andItemsControl.ClearContainerForItemOverride
ItemsPresenter
ItemsPresenter
now only generates containers for simple (non-virtualizing) panelsIItemsPresenterHost
interfaceIItemsPresenter
interfaceItems
propertyItemContainerGenerator
propertyItemsPresenter
can now only be used in anItemsControl
template, not standalone (same as in WPF/UWP etc)VirtualizingPanel`
IVirtualizingPanel
interface has been removed. Virtualizing panels should inherit fromVirtualizingPanel
TabControl
HeaderDisplayMemberBinding
:DisplayMemberBinding
should select the member for the header (in WPF it'sDisplayMemberPath
)Carousel
Panel
;Carousel
syncs the horizontal scroll offset with the currently selected itemVirtualizingCarouselPanel
currently implementedProblems:
Rotate3DTransition
we see the old item flicker up when the transition finishesItemsSourceView
ItemsSourceView.GetOrCreate
. This will allow addressing For Avalonia.Controls.ListBox for Items Property, Support for IList<T> without non-generic IList #8764 in future.IDisposable
- this caused problems when sharingItemsSourceView
sFixed Issues
Fixes #54
Fixes #2177
Fixes #2259
Fixes #2868
Fixes #2936
Fixes #3506
Fixes #4265
Fixes #4701
Fixes #6480
Fixes #7467
#7706 is partially fixed. The stack overflow is fixed, but the
ScrollBar
gets confused, that part will need to be fixed separatelyFixes #8086
Fixes #8181
Fixes #8344
Fixes #8495
Fixes #9269