I need a grouped collection view and I would like to bind it to an ObservableGroupedCollection because I am wanting to update the data and my updates to be reflected in the UI. In order to do this I have adapted the example found here
https://github.com/jfversluis/MauiCollectionViewGroupingSample but I am having a problem with the collection view headers not rendering the data.
To demonstrate my problem I have created a .net 8 maui app and referenced the nuget package CommunityToolkit.Mvvm version 8.2.2.
Here is my viewmodel
using CommunityToolkit.Mvvm.Collections;
using CommunityToolkit.Mvvm.ComponentModel;
namespace TestGroupedCollectionView;
public partial class PageViewModel: ObservableObject
{
public ObservableGroupedCollection<AnimalGroup, Animal> Animals { get; set; } = [];
public PageViewModel()
{
var bearGroup = new AnimalGroup
{
GroupName = "Bears"
};
var bears = new List<Animal>
{
new Animal
{
Name = "American Black Bear"
},
new Animal
{
Name = "Asian Black Bear"
}
};
Animals.Add(new ObservableGroup<AnimalGroup, Animal>(bearGroup, bears));
var monkeys = new List<Animal>
{
new Animal
{
Name = "Baboon"
},
new Animal
{
Name = "Capuchin Monkey",
},
new Animal
{
Name = "Blue Monkey"
},
};
var monkeyGroup = new AnimalGroup
{
GroupName = "Monkeys"
};
Animals.Add(new ObservableGroup<AnimalGroup, Animal>(monkeyGroup, monkeys));
}
}
Here is the animal class
public class Animal
{
public string Name { get; set; } = "";
}
Here is the animal group class
public class AnimalGroup
{
public string GroupName { get; set; } = "";
}
Here is the code behind of my page
namespace TestGroupedCollectionView;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new PageViewModel();
}
}
And here is my xaml code
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:viewmodeldto="clr-namespace:TestGroupedCollectionView"
x:Class="TestGroupedCollectionView.MainPage">
<CollectionView ItemsSource="{Binding Animals}" IsGrouped="True">
<CollectionView.GroupHeaderTemplate>
<DataTemplate>
<Label FontSize="18" FontAttributes="Bold" BackgroundColor="Gray" Text="{Binding GroupName}" />
</DataTemplate>
</CollectionView.GroupHeaderTemplate>
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout>
<Label
Text="{Binding Name}"/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ContentPage>
I have run the code on an emulator, i.e. an Android Studio Pixel 5 and the output you get is:
American Black Bear
Asian Black Bear
Baboon
Capuchin Monkey
Blue Monkey
In other words the group header template is being rendered but the Name text is being left blank. What I am trying to get instead is the following output:
Bears
American Black Bear
Asian Black Bear
Monkeys
Baboon
Capuchin Monkey
Blue Monkey
which as you can see includes the 2 headers, bears and monkeys.
I have tried to add a Datatype like this
<DataTemplate x:DataType="viewmodeldto:AnimalGroup">
<Label FontSize="18" FontAttributes="Bold" BackgroundColor="Gray" Text="{Binding GroupName}" />
</DataTemplate>
But it doesn't make any difference.
To display grouped data in a CollectionView, you may refer to official docs Display grouped data in a CollectionView.
You could make some changes for AnimalGroup,
public class AnimalGroup : ObservableCollection<Animal>
{
public string Name { get; private set; }
public AnimalGroup(string name, ObservableCollection<Animal> animals) : base(animals)
{
Name = name;
}
}
And in your viewModel, use ObservableCollection instead of List.
public partial class PageViewModel : ObservableObject
{
//public ObservableCollection<AnimalGroup> Animals { get; set; } = new ObservableCollection<AnimalGroup>();
[ObservableProperty]
public ObservableCollection<AnimalGroup> animals = new ObservableCollection<AnimalGroup>();
public PageViewModel()
{
Animals.Add(new AnimalGroup("Bears", new ObservableCollection<Animal>
{
new Animal
{
Name = "American Black Bear",
},
new Animal
{
Name = "Asian Black Bear",
}
}));
Then if you want to add some new Animal, just try something like,
Animals[0].Add(new Animal { Name = "My Bear" });
This will also update the UI.
Hope it helps!