Manually group DataGrid items
datagrid, grouping, wpf
Solution
The proper way for grouping is to use a `CollectionView` (for more details: How to Navigate, Group, Sort and Filter Data in WPF). The following is a simple proof of concept application I created for you to show you how to use a `CollectionView` for grouping you data:
This class represents a row in the DataGrid:
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string ZipCode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Image { get; set; }
}
MaindWindow code behind:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Create some test data
var employees =
new ObservableCollection<Employee>
{
new Employee {FirstName = "Mohammed", LastName = "Fadil", Street = "A B C", ZipCode = "123", City = "London", Country = "UK", Image = "/Images/globe.png"},
new Employee {FirstName = "Siraj", LastName = "Hussam", Street = "A B C", ZipCode = "123", City = "London", Country = "UK", Image = "/Images/globe.png"},
new Employee {FirstName = "Ayman", LastName = "Tariq", Street = "A B C", ZipCode = "123", City = "London", Country = "UK", Image = "/Images/globe.png"},
new Employee {FirstName = "Khalid", LastName = "Sheik", Street = "X Y Z", ZipCode = "234", City = "Paris", Country = "France", Image = "/Images/monitor.png"},
new Employee {FirstName = "Hassan", LastName = "Ali", Street = "Q W E R", ZipCode = "544", City = "NY", Country = "USA", Image = "/Images/star.png"},
new Employee {FirstName = "Ehsan", LastName = "Mahmoud", Street = "A B C", ZipCode = "123", City = "London", Country = "UK", Image = "/Images/globe.png"},
new Employee {FirstName = "Idris", LastName = "Sheik", Street = "X Y Z", ZipCode = "234", City = "Paris", Country = "France", Image = "/Images/monitor.png"},
new Employee {FirstName = "Khalil", LastName = "Ali", Street = "Q W E R", ZipCode = "544", City = "NY", Country = "USA", Image = "/Images/star.png"}
};
ICollectionView employeesView =
CollectionViewSource.GetDefaultView(employees);
// Set the grouping by city proprty
employeesView.GroupDescriptions.Add(new PropertyGroupDescription("City"));
// Set the view as the DataContext for the DataGrid
EmployeesDataGrid.DataContext = employeesView;
}
}
The DataGrid XAML code:
<DataGrid Name="EmployeesDataGrid" ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding FirstName}" Header="First Name"/>
<DataGridTextColumn Binding="{Binding LastName}" Header="Last Name"/>
<DataGridTemplateColumn Header="Image">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding Image}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=City}" FontWeight="Bold" Padding="3"/>
</StackPanel>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Expander>
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}" />
<TextBlock Text="{Binding Path=ItemCount}" Margin="8,0,4,0"/>
<TextBlock Text="Element(s)"/>
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</DataGrid.GroupStyle>
</DataGrid>
The result is:
For more information about styling the DataGrid groups please check this post: WPF DataGrid Control > Grouping
Problem
I need to use a data grid and my data looks as follows: firstName, lastName, street, zip, city, country, image In my datagrid I will only show firstName, lastName and image but it has to be grouped after city. Update The code below shows grouped items but the three items I want to display (firstName, lastName, image) are followed by all items (firstName, lastName, street, zip, city, country, image) per row. I think I have to replace the `<ItemsPresenter />` but thats only speculation.. Can anyone help me, I can't manage this on my own... ``` <Grid> <DataGrid ItemsSource="{Binding GroupedMovables}"> <DataGrid.Columns> <DataGridTemplateColumn Header="Preview" Width="SizeToCells" IsReadOnly="True"> <DataGridTemplateColumn.CellTemplate> <DataTemplate> <Image Name="Preview" Height="20" Source="{Binding Image}" HorizontalAlignment="Center" /> </DataTemplate> </DataGridTemplateColumn.CellTemplate> </DataGridTemplateColumn> <DataGridTextColumn Header="first name" Binding="{Binding FirstName}" /> <DataGridTextColumn Header="last name" Binding="{Binding LastName}" /> </DataGrid.Columns> <DataGrid.GroupStyle> <GroupStyle> <GroupStyle.HeaderTemplate> <DataTemplate> <StackPanel> <TextBlock Text="{Binding Path=City}" FontWeight="Bold" Padding="3"/> </StackPanel> </DataTemplate> </GroupStyle.HeaderTemplate> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type GroupItem}"> <Expander> <Expander.Header> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Path=Name}" /> <TextBlock Text="{Binding Path=ItemCount}" Margin="8,0,4,0"/> <TextBlock Text="Element(s)"/> </StackPanel> </Expander.Header> <ItemsPresenter /> </Expander> </ControlTemplate> </Setter.Value> </Setter> </Style> </GroupStyle.ContainerStyle> </GroupStyle> </DataGrid.GroupStyle> </DataGrid> </Grid> ```