WPF datagrid expander and group by group name

<DataGrid ItemsSource="{Binding BooksGroupList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
          AutoGenerateColumns="False"
          ColumnWidth="*"
          HeadersVisibility="Column"
          CanUserAddRows="False"
          IsReadOnly="True"
          VirtualizingPanel.IsContainerVirtualizable="True"
          VirtualizingPanel.IsVirtualizing="True"
          VirtualizingPanel.VirtualizationMode="Recycling">
    <DataGrid.Columns>
        <DataGridTemplateColumn Header="Group">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <Expander Header="{Binding GroupName}" IsExpanded="True">
                        <DataGrid ItemsSource="{Binding Books}"
                                  AutoGenerateColumns="False" 
                                  HeadersVisibility="Column" 
                                  CanUserAddRows="False" 
                                  IsReadOnly="True"
                                  ColumnWidth="*" 
                                  HorizontalScrollBarVisibility="Hidden"
                                  BorderThickness="0"
                                  Margin="0"
                                  FontSize="20"
                                  HorizontalAlignment="Center"
                                  AlternationCount="2"
                                  AlternatingRowBackground="Cyan">                                     
                            <DataGrid.Columns>
                                <DataGridTextColumn Header="Id" Binding="{Binding Id}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="Title" Binding="{Binding Title}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="Author" Binding="{Binding Author}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="Topic" Binding="{Binding Topic}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="Summary" Binding="{Binding Summary}" Width="*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                                <DataGridTextColumn Header="ISBN" Binding="{Binding ISBN}" Width="3*"
                                                    ElementStyle="{StaticResource centerTbkStyle}"/>
                            </DataGrid.Columns>
                        </DataGrid>
                    </Expander>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
    </DataGrid.Columns>
</DataGrid>



BooksGroupList=new ObservableCollection<BookGroup>(booksList.GroupBy(x => x.GroupName)
        .Select(g => new BookGroup
        {
            GroupName=g.Key,
            Books=new ObservableCollection<Book>(g)
        }));

 

 

 

image

 

 

 

image

 

//xaml
<Window x:Class="WpfApp33.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp33"
        mc:Ignorable="d"
        WindowState="Maximized"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <Style TargetType="TextBlock" x:Key="centerTbkStyle">
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="TextAlignment" Value="Center"/>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid ItemsSource="{Binding BooksGroupList,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
                  AutoGenerateColumns="False"
                  ColumnWidth="*"
                  HeadersVisibility="Column"
                  CanUserAddRows="False"
                  IsReadOnly="True"
                  VirtualizingPanel.IsContainerVirtualizable="True"
                  VirtualizingPanel.IsVirtualizing="True"
                  VirtualizingPanel.VirtualizationMode="Recycling">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Group">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Expander Header="{Binding GroupName}" IsExpanded="True">
                                <DataGrid ItemsSource="{Binding Books}"
                                          AutoGenerateColumns="False" 
                                          HeadersVisibility="Column" 
                                          CanUserAddRows="False" 
                                          IsReadOnly="True"
                                          ColumnWidth="*" 
                                          HorizontalScrollBarVisibility="Hidden"
                                          BorderThickness="0"
                                          Margin="0"
                                          FontSize="20"
                                          HorizontalAlignment="Center"
                                          AlternationCount="2"
                                          AlternatingRowBackground="Cyan">                                     
                                    <DataGrid.Columns>
                                        <DataGridTextColumn Header="Id" Binding="{Binding Id}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="Title" Binding="{Binding Title}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="Author" Binding="{Binding Author}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="Topic" Binding="{Binding Topic}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="Summary" Binding="{Binding Summary}" Width="*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                        <DataGridTextColumn Header="ISBN" Binding="{Binding ISBN}" Width="3*"
                                                            ElementStyle="{StaticResource centerTbkStyle}"/>
                                    </DataGrid.Columns>
                                </DataGrid>
                            </Expander>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>



//cs


using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO.Ports;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Collections.ObjectModel;

namespace WpfApp33
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext=this;
            InitData();
        }

        private void InitData()
        {
            BooksGroupList=new ObservableCollection<BookGroup>();
            List<Book> booksList = new List<Book>();
            int idx = 0;
            for (int i = 0; i<100; i++)
            {
                ++idx;
                for (int j = 0; j<10; j++)
                {
                    booksList.Add(new Book()
                    {
                        GroupName=$"GroupName_{idx}",
                        Id=(idx).ToString(),
                        Name=$"Name_{idx}_{j+1}",
                        Topic=$"Topic_{idx}_{j+1}",
                        Author=$"Author_{idx}_{j+1}",
                        ISBN=$"ISBN_{idx}_{j+1}_{Guid.NewGuid().ToString("N")}",
                        Title=$"Title_{idx}_{j+1}",
                        Summary=$"Summary_{idx}_{j+1}"
                    });
                }                
            }

            BooksGroupList=new ObservableCollection<BookGroup>(booksList.GroupBy(x => x.GroupName)
                    .Select(g => new BookGroup
                    {
                        GroupName=g.Key,
                        Books=new ObservableCollection<Book>(g)
                    }));
        }

        public event PropertyChangedEventHandler? PropertyChanged;
        public void OnPropertyChanged([CallerMemberName] string propName = "")
        {
            var handler = PropertyChanged;
            if (handler!=null)
            {
                handler?.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }

        private ObservableCollection<BookGroup> booksGroupList;
        public ObservableCollection<BookGroup> BooksGroupList
        {
            get
            {
                return booksGroupList;
            }
            set
            {
                if (value!=booksGroupList)
                {
                    booksGroupList=value;
                    OnPropertyChanged(nameof(BooksGroupList));
                }
            }
        }

        public class Book
        {
            public string GroupName { get; set; }
            public string Id { get; set; }
            public string Name { get; set; }
            public string Author { get; set; }
            public string ISBN { get; set; }
            public string Title { get; set; }
            public string Summary { get; set; }
            public string Topic { get; set; }
        }


        public class BookGroup
        {
            public string GroupName { get; set; }
            public ObservableCollection<Book> Books { get; set; }
        }
    }
}

 

posted @ 2025-08-13 16:32  FredGrit  阅读(9)  评论(0)    收藏  举报