New to Telerik UI for Xamarin? Download free 30-day trial

Filtering

RadListView provides you with 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

  • Filter: Defines the function used to check whether a data item passes the filter or not.

Example

First, define the ListView in XAML:

<telerikDataControls:RadListView x:Name="listView" ItemsSource="{Binding Items}">
    <telerikDataControls:RadListView.ItemTemplate>
        <DataTemplate>
            <telerikListView:ListViewTemplateCell>
                <telerikListView:ListViewTemplateCell.View>
                    <StackLayout Orientation="Horizontal">
                        <Label Text="Name:"/>
                        <Label Text="{Binding Name}"/>
                        <Label Text=", Age:"/>
                        <Label Text="{Binding Age}"/>
                    </StackLayout>
                </telerikListView:ListViewTemplateCell.View>
            </telerikListView:ListViewTemplateCell>
        </DataTemplate>
    </telerikDataControls:RadListView.ItemTemplate>
</telerikDataControls:RadListView>

Add the following code to the Filtering class:

public Filtering()
{
    InitializeComponent();
    this.BindingContext = new ViewModel();
    listView.FilterDescriptors.Add(new Telerik.XamarinForms.DataControls.ListView.DelegateFilterDescriptor { Filter = this.AgeFilter });
}
private bool AgeFilter(object arg)
{
    var age = ((Item)arg).Age;
    return age >= 25 && age <= 35;
}

Here is the ViewModel class:

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

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

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

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

        return items;
    }
}

And here is the data class:

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

Here is the result after the data is filtered:

Filtering

A sample example how to create ListView with FilterDescriptor can be found in the ListView/Features folder of the SDK Samples Browser application.

Bindable FilterDescriptor

The RadListView control supports binding. What's new is that now the users can control the FilerDescriptor collection through MVVM.

In order to control the FilterDescriptor collection through MVVM:

  1. Create a property of type ObservableCollection in your ViewModel which will contain the needed filters. Here is a sample ViewModel:
public class ViewModel : INotifyPropertyChanged
{
    private ObservableCollection<FilterDescriptorBase> filterDescriptors;
    private bool isFilterSwitchToggled;
    private List<Event> items;

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

    public event PropertyChangedEventHandler PropertyChanged;
    public ObservableCollection<FilterDescriptorBase> FilterDescriptors
    {
        get
        {
            return this.filterDescriptors;
        }
        set
        {
            if (this.filterDescriptors != value)
            {
                this.filterDescriptors = value;
                OnPropertyChanged();
            }
        }
    }
    public bool IsFilterSwitchToggled
    {
        get
        {
            return this.isFilterSwitchToggled;
        }
        set
        {
            if (this.isFilterSwitchToggled != value)
            {
                this.isFilterSwitchToggled = value;
                OnPropertyChanged();
            }
        }
    }

    public List<Event> Items
    {
        get
        {
            return this.items;
        }
        set
        {
            if (this.items != value)
            {
                this.items = value;
                OnPropertyChanged();
            }
        }
    }

    private List<Event> GetItems()
    {
        var results = new List<Event>();

        results.Add(new Event() { Content = "Content of the item", Day = "Tommorow", Category = "A" });
        results.Add(new Event() { Content = "This also happens today", Day = "Yesterday", Category = "A" });
        results.Add(new Event() { Content = "More events today", Day = "Today", Category = "A" });
        results.Add(new Event() { Content = "Go shopping after 19:00", Day = "Yesterday", Category = "B" });
        results.Add(new Event() { Content = "You are now free to do whathever", Day = "Today", Category = "B" });

        results.Add(new Event() { Content = "For tommorow", Day = "Today", Category = "B" });
        results.Add(new Event() { Content = "It is a free day", Day = "Yesterday", Category = "C" });
        results.Add(new Event() { Content = "Go have some fun", Day = "Tommorow", Category = "C" });
        results.Add(new Event() { Content = "Party", Day = "Tommorow", Category = "C" });

        return results;
    }

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.UpdateExistingFilterDescriptor(propertyName);
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

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

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

        if(propertyName.Equals(nameof(IsFilterSwitchToggled)))
        {
            ((DelegateFilterDescriptor)this.FilterDescriptors.FirstOrDefault()).Filter = 
                            this.isFilterSwitchToggled ?
                            new Func<object, bool>((item) => ((Event)item).Category.Equals("C")) :
                            new Func<object, bool>((item) => ((Event)item).Category.Equals("A"));
        }            
    }
}
  1. A sample business model:
public class Event
{
    public string Content { get; set; }
    public string Day { get; set; }
    public string Category { get; set; }
}
  1. Use OneWayToSource binding mode to bind that property to the FilterDescriptors property of RadListView:
<Grid Margin="16,0,0,0">
    <Grid.RowDefinitions>
        <RowDefinition Height="40" />
        <RowDefinition />
    </Grid.RowDefinitions>

    <StackLayout Orientation="Horizontal">
        <StackLayout>
            <Label Text="Filter by Category A/C" />
            <Label Text="Updates existing filter descriptor" FontSize="Micro" TextColor="LimeGreen" LineBreakMode="WordWrap" />
        </StackLayout>
        <Switch IsToggled="{Binding IsFilterSwitchToggled, Mode=OneWayToSource}" AutomationId="FilterCategorySwitch"/>
    </StackLayout>
    <telerikDataControls:RadListView x:Name="listView" Grid.Row="1" 
                                     FilterDescriptors="{Binding FilterDescriptors, 
                                     Mode=OneWayToSource}" 
                                     ItemsSource="{Binding Items}">
        <telerikDataControls:RadListView.ItemTemplate>
            <DataTemplate>
                <telerikListView:ListViewTemplateCell>
                    <telerikListView:ListViewTemplateCell.View>
                        <StackLayout>
                            <Label Text="{Binding Content}" FontSize="Medium" />
                            <Label Text="{Binding Day}" FontSize="Small" TextColor="LimeGreen" />
                            <Label Text="{Binding Category}" FontSize="Micro" TextColor="Red" />
                        </StackLayout>
                    </telerikListView:ListViewTemplateCell.View>
                </telerikListView:ListViewTemplateCell>
            </DataTemplate>
        </telerikDataControls:RadListView.ItemTemplate>
    </telerikDataControls:RadListView>
</Grid>

Here is how this looks like:

FilterDescriptorsMVVM

Bindable Filter Descriptor example can be checked in our SDK Samples Browser application ListView/BindableCollections folder.

See Also

In this article