New to Telerik UI for .NET MAUI? Start a free 30-day trial

.NET MAUI ListView Filtering

The ListView provides the functionality to programmatically filter its data at runtime. This can be achieved through adding filter descriptors that implement the IFilter interface to the RadListView.FilterDescriptors collection. You can use our DelegateFilterDescriptor implementation.

DelegateFilterDescriptor

The DelegateFilterDescriptor property supports a Filter, which defines the function used to check whether a data item passes the filter or not.

1. Define the ListView in XAML:

<telerik:RadListView x:Name="listView" 
                     ItemsSource="{Binding Items}">
    <telerik:RadListView.BindingContext>
        <local:ViewModel/>
    </telerik:RadListView.BindingContext>
    <telerik:RadListView.ItemTemplate>
        <DataTemplate>
            <telerik:ListViewTemplateCell>
                <telerik:ListViewTemplateCell.View>
                    <HorizontalStackLayout>
                        <Label Text="Name:"/>
                        <Label Text="{Binding Name}"/>
                        <Label Text=", Age:"/>
                        <Label Text="{Binding Age}"/>
                    </HorizontalStackLayout>
                </telerik:ListViewTemplateCell.View>
            </telerik:ListViewTemplateCell>
        </DataTemplate>
    </telerik:RadListView.ItemTemplate>
</telerik:RadListView>

2. Add a DelegateFilterDescriptor to the FilerDescriptors collection of the ListView instance:

this.listView.FilterDescriptors.Add(new Telerik.Maui.Controls.Compatibility.DataControls.ListView.ListViewDelegateFilterDescriptor { Filter = this.AgeFilter });

3. Here is the AgeFilter method containing the filtering logic:

private bool AgeFilter(object arg)
{
    var age = ((Person)arg).Age;
    return age >= 25 && age <= 35;
}

4. Define the ViewModel class:

public class ViewModel
{
    public ViewModel()
    {
        this.Items = GetData();
    }

    public ObservableCollection<Person> Items { get; set; }

    private static ObservableCollection<Person> GetData()
    {
        var items = new ObservableCollection<Person>();

        items.Add(new Person { Name = "Tom", Age = 41 });
        items.Add(new Person { Name = "Anna", Age = 32 });
        items.Add(new Person { Name = "Peter", Age = 28 });
        items.Add(new Person { Name = "Teodor", Age = 39 });
        items.Add(new Person { Name = "Lorenzo", Age = 25 });
        items.Add(new Person { Name = "Andrea", Age = 33 });
        items.Add(new Person { Name = "Martin", Age = 36 });
        items.Add(new Person { Name = "Alexander", Age = 29 });
        items.Add(new Person { Name = "Maria", Age = 22 });
        items.Add(new Person { Name = "Elena", Age = 27 });
        items.Add(new Person { Name = "Stefano", Age = 44 });
        items.Add(new Person { Name = "Jake", Age = 31 });
        items.Add(new Person { Name = "Leon", Age = 28 });

        return items;
    }
}

5. Set the Person data class:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

The following image shows the result after the data is filtered:

.NET MAUI ListView Filtering

Bindable Filter Descriptors

The FilerDescriptors collection of the ListView supports binding, which means that you can modify the directly descriptors directly from the ViewModel.

To control the FilterDescriptor collection through MVVM:

1. Create a property of type ObservableCollection<FilterDescriptorBase> in your ViewModel, which will contain the needed filters.

public class ViewModel : NotifyPropertyChangedBase
{
    private ObservableCollection<FilterDescriptorBase> filterDescriptors;
    private bool isFilterSwitchToggled;

    public ViewModel()
    {
        this.Items = GetData();
        this.filterDescriptors = new ObservableCollection<FilterDescriptorBase>();
    }

    public ObservableCollection<Person> Items { get; set; }

    public ObservableCollection<FilterDescriptorBase> FilterDescriptors
    {
        get { return this.filterDescriptors; }
        set { this.UpdateValue(ref this.filterDescriptors, value); }
    }

    public bool IsFilterSwitchToggled
    {
        get { return this.isFilterSwitchToggled; }
        set
        {
            this.UpdateValue(ref this.isFilterSwitchToggled, value);
            UpdateExistingFilterDescriptor("IsFilterSwitchToggled");
        }
    }

    private static ObservableCollection<Person> GetData()
    {
        var items = new ObservableCollection<Person>();

        items.Add(new Person { Name = "Tom", Age = 41 });
        items.Add(new Person { Name = "Anna", Age = 32 });
        items.Add(new Person { Name = "Peter", Age = 28 });
        items.Add(new Person { Name = "Teodor", Age = 39 });
        items.Add(new Person { Name = "Lorenzo", Age = 25 });
        items.Add(new Person { Name = "Andrea", Age = 33 });
        items.Add(new Person { Name = "Martin", Age = 36 });
        items.Add(new Person { Name = "Alexander", Age = 29 });
        items.Add(new Person { Name = "Maria", Age = 22 });
        items.Add(new Person { Name = "Elena", Age = 27 });
        items.Add(new Person { Name = "Stefano", Age = 44 });
        items.Add(new Person { Name = "Jake", Age = 31 });
        items.Add(new Person { Name = "Leon", Age = 28 });

        return items;
    }
    private void UpdateExistingFilterDescriptor(string propertyName)
    {
        if (this.FilterDescriptors == null)
            return;

        if (this.FilterDescriptors.Count == 0)
        {
            this.FilterDescriptors.Add(new ListViewDelegateFilterDescriptor()
            {
                Filter = new Func<object, bool>((item) => ((Person)item).Name.Equals("A"))
            });
        }

        if (propertyName.Equals(nameof(IsFilterSwitchToggled)))
        {
            ((ListViewDelegateFilterDescriptor)this.FilterDescriptors.FirstOrDefault()).Filter =
                            this.isFilterSwitchToggled ?
                            new Func<object, bool>((item) => ((Person)item).Name.StartsWith("T")) :
                            new Func<object, bool>((item) => ((Person)item).Name.StartsWith("A"));
        }
    }

2. Define the data object:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

3. Define the ListView in XAML:

<telerik:RadListView x:Name="listView" 
                                 Grid.Row="1"
                                 ItemsSource="{Binding Items}"
                                 FilterDescriptors="{Binding FilterDescriptors, Mode=OneWayToSource}" >
    <telerik:RadListView.ItemTemplate>
        <DataTemplate>
            <telerik:ListViewTemplateCell>
                <telerik:ListViewTemplateCell.View>
                    <HorizontalStackLayout>
                        <Label Text="Name:"/>
                        <Label Text="{Binding Name}"/>
                        <Label Text=", Age:"/>
                        <Label Text="{Binding Age}"/>
                    </HorizontalStackLayout>
                </telerik:ListViewTemplateCell.View>
            </telerik:ListViewTemplateCell>
        </DataTemplate>
    </telerik:RadListView.ItemTemplate>
</telerik:RadListView>

The following image shows how this looks like:

.NET MAUI ListView Filter Descriptors MVVM

See Also

In this article