I have a ListView Control bound to a ListCollectionView
in a ViewModel.
I wanted to try to group these items but having some problems.
I set the Property grouping in the VM to begin with and then added a GroupStyle
.
C#:
ListCollectionView.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
XAML:
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
However the list is now just the category names, no way to see the items themselves.
I'm not really understanding completely what is going on here. When I create a Template for the GroupStyle
what am I really binding to? Are there other properties besides Name
?
I just added the GroupStyle
to a ListView I has already created where I for example included a ItemTemplate
. Is that something that is messing with the GroupStyle
?
What if the Items in the list belong to another class and I wan't to group based on what instance of class they belong to (it has an ID). I would then have the group name as a property on this parent class. Is that possible?
PARTIAL SOLUTION:
Problem was with the style applied on the ListView. I have no idea what about the style was interefering.
FULL SOLUTION
I wasn't using a ItemsPresenter
in my listbox ControlTemplate
opting to use a Panel with IsItemsHost
set to true
. It seems ItemsPresenter must be used for GroupStyling to work correctly.
I think the error lies elsewhere in your code.
Usually, you expose a collection of Models on your ViewModel
namespace Derp
{
public sealed class ViewModel
{
public ObservableCollection<Model> Items {get;set;}
// initialization code not shown
}
public sealed class Model
{
public string GroupName {get;set;}
public string ModelName {get;set;}
}
}
In your View, you bind a CollectionViewSource to this collection:
<Window.DataContext>
<ViewModel xmlns="clr-namespace:Derp" />
</Window.DataContext>
<Window.Resources>
<CollectionViewSource
Source="{Binding Items}"
x:Key="GroupedItems">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription
PropertyName="GroupName" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
Next, we bind our list control to this CollectionViewSource (using a combo in this example):
<ComboBox
ItemsSource="{Binding Source={StaticResource GroupedItems}}"
DisplayMemberPath="ModelName">
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
</ComboBox>
Where it can get confusing is that, within the GroupStyle, you aren't binding against your Model, you are binding against a collection of Models which is grouped on (in this case) the property "GroupName". The CollectionViewSource groups your Models into collections that extend CollectionViewGroup. These groups have a property called Name
, which contains the common value on which your Models are grouped (the value of the GroupName
property). So, in the HeaderTemplate, you are binding to CollectionViewGroup.Name.