ICollectionView
cannot. GroupStyle.ContainerStyleSelector can. Here is an example.
XAML:
<Window x:Class="WpfWindowDrag.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfWindowDrag="clr-namespace:WpfWindowDrag"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<!--Container style for a groupped item-->
<Style x:Key="RegularContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander Header="{Binding Name}" IsExpanded="True">
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--Container style for root objects (i.e. non grouped)-->
<Style x:Key="RootContainerStyle" TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<ItemsPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!--This guy lets us select choose proper group for an item.-->
<WpfWindowDrag:CountryStyleSelector x:Key="ContainerStyleSelector"
RegularGroupStyle="{StaticResource RegularContainerStyle}"
RootGroup="{StaticResource RootContainerStyle}" />
</Window.Resources>
<Grid>
<ListView x:Name="lv">
<ListView.GroupStyle>
<GroupStyle ContainerStyleSelector="{StaticResource ContainerStyleSelector}" />
</ListView.GroupStyle>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="Name" />
</GridView>
</ListView.View>
</ListView>
</Grid>
</Window>
CS:
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace WpfWindow
{
public partial class Window1 : Window
{
private const int NumberOfRecords = 20;
private readonly ObservableCollection<Person> _myList;
public Window1()
{
InitializeComponent();
var countries = new[] { "", "US", "China", "India", "Japan", "Ukraine" };
var countriesCount = countries.Length;
_myList = new ObservableCollection<Person>();
var rnd = new Random();
for (int i = 0; i < NumberOfRecords; i++)
{
int countryIndex = rnd.Next(countriesCount);
_myList.Add(new Person() { Name = string.Format("Name {0}", i), Country = countries[countryIndex] });
}
ICollectionView view = CollectionViewSource.GetDefaultView(_myList);
view.GroupDescriptions.Add(new PropertyGroupDescription("Country"));
view.SortDescriptions.Add(new SortDescription("Country", ListSortDirection.Ascending));
view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
lv.ItemsSource = view;
}
}
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
public class CountryStyleSelector : StyleSelector
{
public Style RegularGroupStyle { get; set; }
public Style RootGroup { get; set; }
public override Style SelectStyle(object item, DependencyObject container)
{
var cvg = item as CollectionViewGroup;
if (cvg == null)
{
return base.SelectStyle(item, container);
}
return string.IsNullOrEmpty(cvg.Name as string) ? RootGroup : RegularGroupStyle;
}
}
}
Keep in mind though, having items group automatically disables virtualization and impacts performance. If you need something really fast with thousands of items inside you'd probably write your own control or look for 3rd parties.
Cheers, Anvaka.