This page describes how to handle user interaction of the CollectionView
Context menus
Use the SwipeView to define custom commands for each item. Below it's shown an example:
In the following example, the CollectionView is bound to an ObservableCollection so that when an item is removed from the list the control automatically refreshes without reloading the entire list.
Using a simple List or Array it would be necessary to update the entire list using a call to SetState()
The "pull to refresh" feature allows you to execute a command when the user pulls down the collection view control to refresh the list.
Please note again that we're using an ObservableCollection instead of a List or Array so that control can subscribe to collection change events using the System.Collections.Specialized.INotifyCollectionChanged interface and update itself accordingly and efficiently
The below example shows how you can load data incrementally as the user scrolls down the list:
publicrecordPersonWithAddress(string FirstName,string LastName,int Age,string Address);classMainPageLoadDataIncrementallyState{publicObservableCollection<PersonWithAddress> Persons { get; set; }publicbool IsLoading { get; set; }}classMainPageLoadDataIncrementally:Component<MainPageLoadDataIncrementallyState>{privatestaticIEnumerable<PersonWithAddress> GenerateSamplePersons(int count) {var random =newRandom();var firstNames =new[] { "John","Jim","Joe","Jack","Jane","Jill","Jerry","Jude","Julia","Jenny" };var lastNames =new[] { "Brown","Green","Black","White","Blue","Red","Gray","Smith","Doe","Jones" }; var cities = new[] { "New York", "London", "Sidney", "Tokyo", "Paris", "Berlin", "Mumbai", "Beijing", "Cairo", "Rio" };
var persons =newList<PersonWithAddress>();for (int i =0; i < count; i++) {var firstName =firstNames[random.Next(0,firstNames.Length)];var lastName =lastNames[random.Next(0,lastNames.Length)];var age =random.Next(20,60);var city =cities[random.Next(0,cities.Length)];var address =$"{city} No. {random.Next(1,11)} Lake Park";persons.Add(newPersonWithAddress(firstName, lastName, age, address)); }return persons; }protectedoverridevoidOnMounted() {State.Persons=newObservableCollection<PersonWithAddress>(GenerateSamplePersons(100)); base.OnMounted(); }publicoverrideVisualNodeRender() {returnnewContentPage {newGrid("*","*") {newCollectionView() .ItemsSource(State.Persons, RenderPerson) .RemainingItemsThreshold(50) .OnRemainingItemsThresholdReached(LoadMorePersons),newActivityIndicator() .IsRunning(State.IsLoading) .VCenter() .HCenter() } }; }privatevoidLoadMorePersons() {if (State.IsLoading==true) {return; }SetState(s =>s.IsLoading=true);Task.Run(async () => {awaitTask.Delay(3000);foreach (var newPerson inGenerateSamplePersons(50)) { //is not required here to call set state because we don't want to refresh the entire component //the collection view is bound to State.PersonsState.Persons.Add(newPerson); }SetState(s =>s.IsLoading=false); }); }privateVisualNodeRenderPerson(PersonWithAddress person) {returnnewVStack(spacing:5) {newLabel($"{person.FirstName} {person.LastName} ({person.Age})"),newLabel(person.Address) .FontSize(12) } .HeightRequest(56) .VCenter(); }}
You may be tempted to use code like SetState(s => s.Persons.Add(person)) but, in this specific case, it's not required: the CollectionView is bound to the Persons ObservableCollection and it's automatically refreshed at every change of the collection without requiring the component refresh.
Please note that, in all other cases (i.e. excluding ObservableCollection properties) you must update the state using the SetState() method when you need to update the view.