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

.NET MAUI ListView Multi-Level Grouping

This article provides an overview on how you can enable multi-level grouping in the ListView.

Before proceeding, go through the Grouping Overview topic.

1. Create the following business object:

public class City
{
    public string Continent { get; set; }
    public string Name { get; set; }
    public string Country { get; set; }
}

2. Create a ViewModel class as shown below:

public class GroupingViewModel : NotifyPropertyChangedBase
{
    public ObservableCollection<City> Cities { get; set; }

    public GroupingViewModel()
    {
        this.Cities = new ObservableCollection<City>()
        {
            new City() { Name = "Barcelona", Country = "Spain", Continent = "Europe"},
            new City() { Name = "Madrid", Country = "Spain", Continent = "Europe" },
            new City() { Name = "Rome", Country = "Italy", Continent = "Europe" },
            new City() { Name = "Florence", Country = "Italy", Continent = "Europe" },
            new City() { Name = "London", Country = "England", Continent = "Europe" },
            new City() { Name = "Manchester", Country = "England", Continent = "Europe"},
            new City() { Name = "New York", Country = "USA", Continent = "North America" },
            new City() { Name = "Boston", Country = "USA",  Continent = "North America" }
         };
    }
}

3. To visualize the hierarchical relation between groups, add a custom GroupHeaderTemplate (of type DataTemplate) to the Resources of your page:

<ResourceDictionary>
    <multiLevelGrouping:LevelToMarginConverter x:Key="LevelToMarginConverter" />
    <DataTemplate x:Key="ListViewItemTemplate">
        <telerik:ListViewTemplateCell>
            <telerik:ListViewTemplateCell.View>
                <Grid HeightRequest="40" Padding="48, 0, 0, 0">
                    <Label Text="{Binding Name}" TextColor="#6F6F70" FontSize="Small" VerticalOptions="Center" />
                </Grid>
            </telerik:ListViewTemplateCell.View>
        </telerik:ListViewTemplateCell>
    </DataTemplate>
    <DataTemplate x:Key="ListViewMultiLevelGroupHeaderTemplate">
        <Grid HeightRequest="40" BackgroundColor="#F1F2F5">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Label Text="&#xE806;" Margin="{Binding Level, Converter={StaticResource LevelToMarginConverter}}" 
                   TextColor="DarkGray" FontFamily="TelerikFontExamples" FontSize="Medium" VerticalOptions="Center">
                <Label.Triggers>
                    <DataTrigger TargetType="Label" Binding="{Binding IsExpanded}" Value="True">
                        <Setter Property="Text" Value="&#xE80D;" />
                    </DataTrigger>
                </Label.Triggers>
            </Label>
            <Label Margin="8, 0, 0, 0" Text="{Binding }" Grid.Column="1" TextColor="DarkGray" FontSize="Medium" VerticalOptions="Center" />
        </Grid>
    </DataTemplate>
    <telerik:ListViewGroupStyle x:Key="ListViewGroupHeaderStyle" BackgroundColor="Transparent" />
</ResourceDictionary>

4. The LevelToMarginConverter calculates the margin of each group header according to its Level:

public class LevelToMarginConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value != null)
        {
            var level = (int)value;
            return new Thickness(((level - 1) * 20) + 8, 12, 0, 6);
        }
        else return value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}

5. Add the RadListView definition with two PropertyGroupDescriptors as shown in the next snippet:

<telerik:RadListView x:Name="listView" ItemsSource="{Binding Cities}"
                     ItemTemplate="{StaticResource ListViewItemTemplate}"
                     GroupHeaderTemplate="{StaticResource ListViewMultiLevelGroupHeaderTemplate}"
                     GroupHeaderStyle="{StaticResource ListViewGroupHeaderStyle}">
    <telerik:RadListView.BindingContext>
        <local:GroupingViewModel/>
    </telerik:RadListView.BindingContext>
    <telerik:RadListView.GroupDescriptors>
        <telerik:ListViewPropertyGroupDescriptor PropertyName="Continent"/>
        <telerik:ListViewPropertyGroupDescriptor PropertyName="Country"/>
    </telerik:RadListView.GroupDescriptors>
</telerik:RadListView>

6. Include the telerik namespace:

xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui" 

The following image shows the final result.

.NET MAUI ListView Multi-Level Grouping

See Also

In this article