Sorting in .NET MAUI ListView (SfListView)
22 Jul 202413 minutes to read
The SfListView
supports sorting the data either in ascending or descending order by using the DataSource.SortDescriptors property and custom logic.
To get start quickly with sorting in .NET MAUI ListView, you can check on this video:
NOTE
When the
ItemsSource
is changed for a ListView,DataSource.SortDescriptors
will be cleared by default. You need to addDataSource.SortDescriptors
again after changing theItemsSource
, if you want to retain sorting in the listview.
NOTE
To sort the newly added listview items at runtime, set the SfListView.DataSource.LiveDataUpdateMode to LiveDataUpdateMode.AllowDataShaping.
Programmatic sorting
Sorting the data by creating a SortDescriptor with the required property name and direction and adding it into the DataSource.SortDescriptors property.
SortDescriptor
object holds the following three properties:
- PropertyName: Describes the name of the sorted property.
- Direction: Describes an object of type ListSortDirection that defines the sorting direction.
- Comparer: Describes the comparer to be applied when sorting takes place.
<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.Maui.ListView;assembly=Syncfusion.Maui.ListView"
xmlns:data="clr-namespace:Syncfusion.Maui.DataSource;assembly=Syncfusion.Maui.DataSource" >
<syncfusion:SfListView x:Name="listView">
<syncfusion:SfListView.DataSource>
<data:DataSource>
<data:DataSource.SortDescriptors>
<data:SortDescriptor PropertyName="ContactName" Direction="Ascending"/>
</data:DataSource.SortDescriptors>
</data:DataSource>
</syncfusion:SfListView.DataSource>
</syncfusion:SfListView>
</ContentPage>
listView.DataSource.SortDescriptors.Add(new SortDescriptor()
{
PropertyName = "ContactName",
Direction = ListSortDirection.Ascending,
});
listView.RefreshView();
NOTE
It is mandatory to specify the
PropertyName
ofSortDescriptor
.
Custom sorting
Sort the items based on the custom logic and it can be applied to either SfListView.DataSource.SortComparer property or SortDescriptor.Comparer, which is added into the DataSource.SortDescriptors collection.
NOTE
If the
PropertyName
in the SortDescriptor andGroupDescriptor
are same, then the GroupResult will be passed as parameters for theSortDescriptor.Comparer
. Otherwise, data objects are passed. To sort the data items alone, set the differentPropertyName
in both theSortDescriptor
and theGroupDescriptor
properties.
<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.Maui.ListView;assembly=Syncfusion.Maui.ListView"
xmlns:data="clr-namespace:Syncfusion.Maui.DataSource;assembly=Syncfusion.Maui.DataSource">
<ContentPage.Resources>
<ResourceDictionary>
<local:CustomSortComparer x:Key="CustomSortComparer" />
</ResourceDictionary>
</ContentPage.Resources>
<syncfusion:SfListView x:Name="listView">
<syncfusion:SfListView.DataSource>
<data:DataSource>
<data:DataSource.SortDescriptors>
<data:SortDescriptor Comparer="{StaticResource CustomSortComparer}"/>
</data:DataSource.SortDescriptors>
</data:DataSource>
</syncfusion:SfListView.DataSource>
</syncfusion:SfListView>
</ContentPage>
listView.DataSource.SortDescriptors.Add(new SortDescriptor()
{
Comparer = new CustomSortComparer()
});
public class CustomSortComparer : IComparer<object>
{
public int Compare(object x, object y)
{
if (x.GetType() == typeof(ListViewContactsInfo))
{
var xitem = (x as ListViewContactsInfo).ContactName;
var yitem = (y as ListViewContactsInfo).ContactName;
if (xitem.Length > yitem.Length)
{
return 1;
}
else if (xitem.Length < yitem.Length)
{
return -1;
}
else
{
if (string.Compare(xitem, yitem) == -1)
return -1;
else if (string.Compare(xitem, yitem) == 1)
return 1;
}
}
return 0;
}
}
You can download the entire sample code from the github.
Sort the items on header tapped
To apply the sorting when tapping the header, handle the ItemTapped event of the SfListView
.
<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.Maui.ListView;assembly=Syncfusion.Maui.ListView"
xmlns:data="clr-namespace:Syncfusion.Maui.DataSource;assembly=Syncfusion.Maui.DataSource">
<syncfusion:SfListView x:Name="listView" ItemSize="60"
ItemsSource="{Binding customerDetails}"
ItemTapped="ListView_ItemTapped"
IsStickyHeader="True">
<syncfusion:SfListView.HeaderTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout BackgroundColor="Teal">
<Label TextColor="White" FontSize="20" FontAttributes="Bold" Text="CustomerDetails" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</syncfusion:SfListView.HeaderTemplate>
</syncfusion:SfListView>
</ContentPage>
listView = new SfListView();
listView.ItemsSource = viewModel.customerDetails;
listView.ItemSize = 60;
listView.ItemTapped += ListView_ItemTapped;
listView.IsStickyHeader = true;
listView.HeaderTemplate = new DataTemplate(() =>
{
var stackLayout = new StackLayout { BackgroundColor = Colors.Teal };
var label = new Label { Text = "CustomerDetails", TextColor = Colors.White,
FontAttributes = FontAttributes.Bold, FontSize = 20 };
stackLayout.Children.Add(label);
return stackLayout;
});
When the ItemTapped
event is raised for the Header, add the SortDescriptor and refresh the view.
private void ListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
//Applying sorting to the underlying data when the header item is tapped.
if (e.ItemType == ItemType.Header && listView.IsStickyHeader)
{
listView.DataSource.SortDescriptors.Clear();
listView.DataSource.SortDescriptors.Add(new SortDescriptor()
{
PropertyName = "ContactName",
Direction = ListSortDirection.Ascending
});
}
}
Sort the items along with grouping
The SfListView
allows sorting and grouping the items by adding the DataSource.GroupDescriptors and the DataSource.SortDescriptors with required property name.
Sorting with grouping by year
Sorting and grouping the items by using KeySelector based on retuning the year value of the date-time property.
<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.Maui.ListView;assembly=Syncfusion.Maui.ListView"
xmlns:data="clr-namespace:Syncfusion.Maui.DataSource;assembly=Syncfusion.Maui.DataSource">
<ContentPage.Content>
<syncfusion:SfListView x:Name="listView" ItemsSource="{Binding Items}" ItemSize="50">
<syncfusion:SfListView.GroupHeaderTemplate>
<DataTemplate>
<Grid>
<Label Text= "{Binding Key}" BackgroundColor="Teal" FontAttributes="Bold" TextColor="White"/>
</Grid>
</DataTemplate>
</syncfusion:SfListView.GroupHeaderTemplate>
</syncfusion:SfListView>
</ContentPage.Content>
</ContentPage>
var listView = new SfListView();
listView.ItemSize = 50;
listView.ItemsSource = viewModel.Items;
listView.GroupHeaderTemplate = new DataTemplate(() =>
{
var grid = new Grid();
var headerLabel = new Label
{
TextColor = Colors.White,
FontAttributes = FontAttributes.Bold,
BackgroundColor=Colors.Teal
};
headerLabel.SetBinding(Label.TextProperty, new Binding("key"));
grid.Children.Add(headerLabel);
return grid;
});
listView.DataSource.GroupDescriptors.Add(new GroupDescriptor()
{
PropertyName = "DateOfBirth",
KeySelector = (object obj1) =>
{
var item = (obj1 as Contacts);
return item.DateOfBirth.Year;
},
});
this.listView.DataSource.SortDescriptors.Add(new SortDescriptor()
{
PropertyName = "DateOfBirth",
Direction = ListSortDirection.Ascending
});
The following screenshot shows the output when items are sorted by year. Download the entire source code from GitHub here
Sorting with grouping by month and year
Sorting and grouping the items by using KeySelector
based on returning the month and year value of the date-time property.
<ContentPage xmlns:syncfusion="clr-namespace:Syncfusion.Maui.ListView;assembly=Syncfusion.Maui.ListView"
xmlns:data="clr-namespace:Syncfusion.Maui.DataSource;assembly=Syncfusion.Maui.DataSource">
<ContentPage.Content>
<syncfusion:SfListView x:Name="listView">
<syncfusion:SfListView.DataSource>
<data:DataSource>
<data:DataSource.GroupDescriptors>
<data:GroupDescriptor PropertyName="ContactName" />
</data:DataSource.GroupDescriptors>
<data:DataSource.SortDescriptors>
<data:SortDescriptor PropertyName="ContactName" Direction="Ascending"/>
</data:DataSource.SortDescriptors>
</data:DataSource>
</syncfusion:SfListView.DataSource>
</syncfusion:SfListView>
</ContentPage.Content>
</ContentPage>
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
listView.DataSource.GroupDescriptors.Add(new GroupDescriptor()
{
PropertyName = "DateOfBirth",
KeySelector = (object obj1) =>
{
var item = (obj1 as Contacts);
return item.DateOfBirth.Month + "/" + item.DateOfBirth.Year;
},
Comparer = new CustomGroupComparer()
});
this.listView.DataSource.SortDescriptors.Add(new SortDescriptor()
{
PropertyName = "DateOfBirth",
Direction = ListSortDirection.Ascending
});
}
}
The following screenshot shows the output when items are sorted by month and year.