Working with ListView in .NET MAUI ListView (SfListView)

13 Jul 202615 minutes to read

Interacting with ListView Items

Loaded event

The Loaded event is triggered when the SfListView is loaded into view for the first time.

<sync:SfListView x:Name="listView"
                 ItemsSource="{Binding Customers}"
                 Loaded="ListView_Loaded" />
listView.Loaded += ListView_Loaded;

private void ListView_Loaded(object sender, Syncfusion.Maui.ListView.ListViewLoadedEventArgs e)
{
   listView.SelectedItems.Add(viewModel.Customers[2]);
}

The Loaded event is used for the following use cases:

Tapped event

The ItemTapped event will be triggered whenever tapping the item. Here, TapCommandParameter property sets the parameter for SfListView.TapCommand and its default value is ItemTappedEventArgs. ItemTappedEventArgs has the following members, which provides information for ItemTapped event:

  • ItemType: It gets the type of the tapped item.
  • DataItem: The underlying data associated with the tapped item.
  • Position: Gets the touch position in the tapped item.
<sync:SfListView x:Name="listView"
                 ItemsSource="{Binding InboxInfo}"
                 ItemTapped="ListView_ItemTapped" />
listView.ItemTapped += ListView_ItemTapped;

private void ListView_ItemTapped(object sender, Syncfusion.Maui.ListView.ItemTappedEventArgs e)
{
    if (e.DataItem == viewModel.InboxInfo[0])
      viewModel.InboxInfo.Remove(e.DataItem as ListViewInboxInfo);
}

The ItemTapped event is used for the following use cases:

  • To show the context menu.
  • To navigate to another page.
  • To delete the item in the list view at runtime.
  • To display the item details into another view.
  • To expand the view like, accordion.
  • To change the underlying bound data.
  • To skip other events like selection events if the Handled property set to true.

ItemDoubleTapped event

The ItemDoubleTapped has the following members which provides information for the ItemDoubleTapped event:

  • ItemType: It gets the type of double tapped item.
  • DataItem: The underlying data associated with the double tapped item as its arguments.
  • Position: Gets the touch position in the double tapped item.
listView.ItemDoubleTapped += ListView_ItemDoubleTapped;

private void ListView_ItemDoubleTapped(object sender, Syncfusion.Maui.ListView.ItemDoubleTappedEventArgs e)
{
    var listViewInboxInfo = new ListViewInboxInfo();
    listViewInboxInfo.Title = "Bryce Thomas";
    listViewInboxInfo.Subject = "Congratulations on the move!";
    viewModel.InboxInfo.Add(listViewInboxInfo);
}

The ItemDoubleTapped event is used for the following use cases:

  • To show the context menu.
  • To delete the item in the list view at runtime.
  • To change the underlying bound data.

ItemRightTapped event

The ItemRightTapped event will be triggered whenever the item is right tapped. The ItemRightTappedEventArgs has the following members providing information for the ItemRightTapped event:

NOTE

Platform behavior: ItemRightTapped is only raised on platforms that support a right-click or secondary-button gesture, such as Windows (WinUI), macOS (Mac Catalyst), and desktop targets. It is not raised on iOS and Android, which do not expose a right-click gesture. On iOS and Android, use the ItemLongPress event instead to provide a similar context-menu experience.

  • ItemType: Gets the type of right tapped item.
  • DataItem: The underlying data associated with the right-tapped item.
  • Position: Gets the touch position in the right tapped item.
listView.ItemRightTapped += ListView_ItemRightTapped;

private void ListView_ItemRightTapped(object sender, Syncfusion.Maui.ListView.ItemRightTappedEventArgs e)
{
    DisplayAlert("Item RightTapped", "ListView item right tapped", "Close");
}

ItemLongPress event

The ItemLongPress event will be triggered whenever long pressing the item. Here, LongPressCommandParameter sets the parameter for SfListView.LongPressCommand and its default value is ItemLongPressEventArgs. ItemLongPressEventArgs has the following members, which provides information for ItemLongPress event:

NOTE

Platform behavior: ItemLongPress is supported on iOS, Android, Windows (WinUI), and macOS (Mac Catalyst). However, on Windows (WinUI), the long-press is triggered by touch only; it is not raised by a mouse press-and-hold gesture.

  • ItemType: It gets the type of the long pressed item.
  • DataItem: The underlying data associated with the long-pressed item.
  • Position: Gets the touch position in the holding item.
listView.ItemLongPress += ListView_ItemLongPress;

pri// Note: this comparison uses reference equality, not value equality.
   if (e.DataItem == viewModel.InboxInfo[3])
      viewModel.InboxInfo.Remove(e.DataItem as ListViewInboxInfo);
   if (e.DataItem == viewModel.InboxInfo[3])
      viewModel.InboxInfo.Remove(e.DataItem as ListViewInboxInfo);
}

The ItemLongPress event is used for the following use cases:

  • To show the context menu.

NOTE

Interaction events of the SfListView will be triggered for all the ListViewItems like HeaderItem, FooterItem, GroupHeaderItem, LoadMoreItem, and RecordItem. Handle the interaction actions based on the ItemType of the event args.

ItemAppearing

The ItemAppearing is triggered when items appear in the view while scrolling, loading, or navigating from one page to another. The ItemAppearingEventArgs has the following member, which provides information of appearing Items.

  • DataItem: The underlying data associated with the appearing item.
listView.ItemAppearing += listView_ItemAppearing;

private void listView_ItemAppearing(object sender,  Syncfusion.Maui.ListView.ItemAppearingEventArgs e)
{
    if (e.DataItem == viewModel.BookInfo[0])
        Debug.WriteLine((e.DataItem as BookInfo).BookName);

    // If the DataItem value is "Header", then it's a header item.
    if (e.DataItem == "Header")
        Debug.WriteLine("Header is Appeared");
}

The ItemAppearing event is used for the following use cases:

  • To determine when an item appears in the view.
  • To change the background color of the appearing item, use the converter.

ItemDisappearing

The ItemDisappearing event is triggered when items disappear from the view while scrolling, disposing, or navigating from one page to another. The ItemDisappearingEventArgs has the following member, which provides information about disappearing Items:

  • DataItem: The underlying data associated with the disappearing item.
listView.ItemDisappearing += listView_ItemDisappearing;

private void listView_ItemDisappearing(object sender, Syncfusion.Maui.ListView.ItemDisappearingEventArgs e)
{
    if (e.DataItem == viewModel.BookInfo[0])
        Debug.WriteLine((e.DataItem as BookInfo).BookName);

    // If the DataItem value is "Footer" then it's a Footer item.
    if (e.DataItem == "Footer")
        Debug.WriteLine("Footer is Disappeared");
}

The ItemDisappearing event is used for the following use cases:

  • To determine when an item disappears from the view.

Improving ListView performance

The .NET MAUI ListView (SfListView) has been built from the ground up with an optimized view reuse strategy to provide the best possible performance on the .NET MAUI platform, even when loading large data sets. The following techniques are used to improve performance of the SfListView:

  • Bind the ItemsSource property to an IList collection instead of an IEnumerable collection because IEnumerable collection does not support random access.
  • The SfListView gets refreshed each and every time when a new item is added into the underlying collection. When adding items at runtime, the DataSource gets refreshed. To avoid this behavior, use BeginInit() to stop the RefreshView() calling in each time, and use EndInit() to start the RefreshView() calling when adding number of finished items.
  • Avoid loading complex layout in template of listview. For example, loading large-size images or nested containers degrades the scrolling performance. This practice commonly degrades performance in all platforms, and particularly more in Android version API level 19. So, use fewer elements and images with small size and resolution to achieve the maximum performance.
  • Avoid placing the SfListView inside ScrollView for the following reasons:
    • The SfListView implement its own scrolling.
    • The SfListView will not receive any gestures as they are handled by the parent ScrollView.
    • If the SfListView loads inside the ScrollView, an explicit HeightRequest should be set.
  • Avoid changing the cell layout based on the BindingContext. This incurs large layout and initialization costs.
  • Implement a model class inherited with INotifyPropertyChanged interface to notify the property changes at runtime.
  • Use an ObservableCollection<T> as the bound ItemsSource so that additions, removals, and property updates are propagated to the UI automatically. The sample event handlers in this document (e.g., viewModel.InboxInfo.Remove(...)) assume an ObservableCollection<ListViewInboxInfo>.

Scrolling ListView without virtualization

The SfListView allows you to scroll by loading the entire collection of items inside the ScrollView and defining the total extent of its container to HeightRequest in the Loaded event.

<ScrollView>
   <sync:SfListView x:Name="listView" ItemsSource="{Binding BookInfo}" Loaded="listView_Loaded"/>
</ScrollView>
using System.Reflection;
using Syncfusion.ListView.Control.Helpers;

public partial class MainPage : ContentPage
{
	public MainPage()
	{
		InitializeComponent();
	}

	private void listView_Loaded(object sender, ListViewLoadedEventArgs e)
	{
		var container = listView.GetVisualContainer();
		var extent = (double)container.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == "TotalExtent").GetValue(container);
		listView.HeightRequest = extent;
	}
}

NOTE

The TotalExtent property is accessed via reflection because it is an internal member. This approach is unsupported and may break when the control is updated. Prefer using the AutoFitMode="Height" approach below whenever possible.

When SfListView is in AutoFitMode as Height, the extent of the ListView will be updated only while scrolling. So you can resize the ListView in the VisualContainer PropertyChanged event handler as shown in the following code sample.

<ScrollView>
   <sync:SfListView x:Name="listView" AutoFitMode="Height" ItemsSource="{Binding BookInfo}" Loaded="listView_Loaded"/>
</ScrollView>
using Syncfusion.ListView.Control.Helpers;
public partial class MainPage : ContentPage
{
    VisualContainer visualContainer;
    bool loaded;

    public MainPage()
    {
        InitializeComponent();
        visualContainer = listView.GetVisualContainer();
        visualContainer.PropertyChanged += VisualContainer_PropertyChanged;
    }

    private void VisualContainer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Height" && listView.HeightRequest != visualContainer.Height && loaded)
            listView.HeightRequest = visualContainer.Height;
    }

    private void listView_Loaded(object sender, ListViewLoadedEventArgs e)
    {
        var extent = (double)visualContainer.GetType().GetRuntimeProperties().FirstOrDefault(x => x.Name == "TotalExtent").GetValue(visualContainer);
        listView.HeightRequest = extent;
        loaded = true;
    }
}

NOTE

To avoid extra space below the list, make sure the ItemSize property value is not specified while loading in AutoFitMode. After ListView has been loaded, update the size of the container to render all the list items in the view.

The following limitations should be noted when using the previous approaches:

  • As the entire list items are loaded inside the parent ScrollView element, the ItemAppearing and ItemDisappearing events will not be triggered when scrolling.
  • When performing keyboard navigation, the view cannot be scrolled automatically while navigating out of view.
  • Touch action scrolling will be handled in all platforms, and SfListView scrolling will be handled by the parent ScrollView.

Rendering ListView when loading in different layouts

Behavior depends on the parent layout:

  • Measures and lays out the control the same way as the .NET MAUI ListView, when the ListView is loaded inside the layouts such as StackLayout, ScrollView, and Grid, in which the RowDefinition or ColumnDefinition is set to Auto. In all other layouts, the ListView size will be allocated from the framework.
  • Sets the value of total extent to the HeightRequest of ListView, because the scrolling will be handled by the parent ScrollView, when ListView is loaded inside the StackLayout with base parent as ScrollView and multiple elements inside the StackLayout.

Refresh view

You can refresh the view by using the RefreshView method. Use it to refresh the items in the ListView at runtime while updating the view.

listView.RefreshView();

How to

Filter ListView items based on another ListView selection

To filter the ListView items based on the item selection in another ListView, use the SfListView.DataSource.Filter property.

private void ItemTapped(Syncfusion.Maui.ListView.ItemTappedEventArgs e)
{
    tappedPinedInfo = e.DataItem as PinnedInfo;
    if (tappedPinedInfo.IsFavorite)
    {
        secondLV.DataSource.Filter = FilterDepartures;
        tappedPinedInfo.IsFavorite = false;
    }
    else
    {
        secondLV.DataSource.Filter = null;
        tappedPinedInfo.IsFavorite = true;
    }
    secondLV.DataSource.RefreshFilter();
}

private bool FilterDepartures(object obj)
{
    var departureInfo = obj as DepartureInfo;
    if (tappedPinedInfo == null)
        return true;

    if (departureInfo.Name.ToLower().Contains(tappedPinedInfo.Name.ToLower())
            || departureInfo.RouteName.ToLower().Contains(tappedPinedInfo.RouteName.ToLower()))
        return true;
    else
        return false;
}

See also

How to set the font size for .NET MAUI ListView (SfListView)