-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
ItemsRepeater eagerly enumerates the IList<T> it's bound to #6904
Comments
Virtualization of ItemsRepeater means that only 2-3 children controls will be rendered instead of 20 at a time. It does not guarantees "only be called 2 or 3 times". Moreover ItemsRepeater can't work with IEnumerable efficiently, because it needs materialized list of objects (so generic From source code you can see that your collection must implement IList (and not
IList is definitely not expected to work in this way, when each indexer call or enumeration creates new item without any caching. Usually all the data is predefined. If you want to achieve lazy loading of items, you need to use handle scrolling events, do your async operation (which can take 500ms or more but without UI block) and update source list with new items. Note that source list much be of ObservableCollection type of any other that implements INotifyPropertyChanged (and IList of course). |
Hi @uxmal I have found the it may be useful to use // In your ViewModel:
// The property to bind to:
public Task<int> AsyncContent => GetContentAsync();
// the async operation
private async Task<int> GetContentAsync()
{
await Task.Delay(500); // Simulate long running operation
return MyIndex;
} and in your xaml: <TextBlock Text={Binding AsyncContent^} /> for an example please see: Happy coding @maxkatz6 ► Should I provide a PR to the docs with an sample how to bind to tasks? |
@timunie we should have docs for "^" bindinds operator, don't we? If not, or if there is no any example of usage, if would be useful, thanks. |
@uxmal Ui virtualization and data virtualization are totally different things |
Send a PR to the docs: https://github.com/AvaloniaUI/Documentation/pull/157 |
Describe the bug
It seems that an
ItemsRepeater
nested inside aScrollViewer
"eagerly" enumerates all the items of theIList<T>
that is is bound to. The advertised behaviour is that the list of items is "virtualized", which to me implies that theItemsRepeater
should only iterate enough times to get the items it needs to create its visual state. E.g. if I have a list of 100,000 items, but the visible area of the containingScrollViewer
is only large enough to display 2 items, I expectItemsRepeater
to only fetch the first two items (or at most a handful).To Reproduce
I've created a VS2019 solution that exhibits the problem (https://github.com/uxmal/avalonia-6904). Just start the program and you'll notice that it takes a few seconds to start up, as 20 instances of class
ExpensiveObject
are being created, even though theIList<T>
container they live in takes steps to defer their construction untilIEnumerable<T>.MoveNext()
gets called.In the class
MainWindowViewModel
you will see the collection being bound to theItems
property ofItemsRepeater
, calledExpensiveObjects
. There are three initializers (two of which are commented out).MakeVirtualList
creates an instance of a collection class implementingIList<T>
that creates expensive objects on the fly. It takes 500 msec to create each object. You can see from the startup time how the caller is greedily enumerating all the items in the collection, rather than stopping after the first fiew.Expected behavior
My expectation is that the
IEnumerable<T>.MoveNext()
method should only be called 2 or 3 times (in the code sample provided), rather than the full 20.Desktop (please complete the following information):
The text was updated successfully, but these errors were encountered: