WPF DataGrid表头合并且动态添加列

Posted t-arf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF DataGrid表头合并且动态添加列相关的知识,希望对你有一定的参考价值。

DataGrid要实现表头合并的效果。首先使用DataGridTemplate作为列。同时修改HeaderTemplate。但是效果没有那么好且有其他问题。

真正的修改的地方是修改HeaderStyle的DataGridColumnHeader。

内容模板则是修改CellTemplate就好了

 

如果要是同态添加列则是需要使用继承DataGridTemplate的类。

重写GenerateElement方法,并设置好内容模板的数据源。

 

所以大部分的内容都是C#代码,Xaml的部分则就是datatemplate的部分。

 

 

技术图片

 

xaml代码

 <Window.Resources>
        <local:SetWidthConvert x:Key="SetWidthConvert"/>
        <DataTemplate x:Key="CDT">
            <ItemsControl x:Name="ic1"  ItemsSource="{Binding List[0].TestType}" Margin="-1">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel Orientation="Horizontal"/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Border BorderThickness="0,0,1,0" BorderBrush="Black"  MinWidth="30"   >
                            <Border.Width>
                                <MultiBinding Converter="{StaticResource SetWidthConvert}" >
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=ItemsControl}" Path="ActualWidth"/>
                                    <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=ItemsControl}" Path="ItemsSource.Count"/>
                                </MultiBinding>
                            </Border.Width>
                            <TextBlock   HorizontalAlignment="Center" Text="{Binding  }"/>
                        </Border>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DataTemplate>
        <ControlTemplate x:Key="CT1" TargetType="DataGridColumnHeader">
            <Border BorderThickness="0,0,1,0" BorderBrush="Black" >
                <Grid MinHeight="120" x:Name="g1" Margin="-1"  DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=DataGridColumnHeader},Path=Column.ItemSource}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                        <RowDefinition Height="auto"/>
                    </Grid.RowDefinitions>
                    <TextBlock Text="{Binding  RequestName}"  HorizontalAlignment="Center"   VerticalAlignment="Center"/>
                    <Border Grid.Row="1"  BorderBrush="Black" BorderThickness="0,1,0,0"    >
                        <ItemsControl ItemsSource="{Binding RelativeSource={RelativeSource Mode=Self}, Path=DataContext[0].RequestNumList}" x:Name="ic"  >
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"/>
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <Border BorderThickness="0,0,1,0"  BorderBrush="Black"  >
                                        <Border.Width>
                                            <MultiBinding Converter="{StaticResource SetWidthConvert}" >
                                                <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=ItemsControl}" Path="ActualWidth"/>
                                                <Binding  RelativeSource="{RelativeSource Mode=FindAncestor,AncestorLevel=1,AncestorType=ItemsControl}" Path="ItemsSource.Count"/>
                                            </MultiBinding>
                                        </Border.Width>
                                        <TextBlock  VerticalAlignment="Center"  HorizontalAlignment="Center" Text="{Binding   }" FontSize="15" />
                                    </Border>
                                </DataTemplate>
                            </ItemsControl.ItemTemplate>
                        </ItemsControl>
                    </Border>
                </Grid>
            </Border>
        </ControlTemplate>
        <Style x:Key="s1" TargetType="DataGridColumnHeader">
            <Setter Property="Template" Value="{StaticResource CT1 }"/>
        </Style>
    </Window.Resources>
    <Grid>
        <DataGrid x:Name="DG" AutoGenerateColumns="False" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="课程名称"    Binding="{Binding  SchoolName}" Width="150"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

 

C#代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;

namespace 表头合并
{
    class SetWidthConvert : IMultiValueConverter, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnChanged(PropertyChangedEventArgs args) => this.PropertyChanged?.Invoke(this, args);

        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
           
            var w1 = (double)values[0];
            var w2 = System.Convert.ToDouble(values[1]);
            return w1 / w2;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    public class DataNewColumn : DataGridTemplateColumn
    {
        public static readonly DependencyProperty ItemSourceProperty = DependencyProperty.Register("ItemSource", typeof(object), typeof(DataNewColumn));
        public object ItemSource
        {
            get
            {
                return (object)GetValue(ItemSourceProperty);

            }
            set
            {
                SetValue(ItemSourceProperty, value);
            }
        }
 
        protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
        {
            cell.BorderThickness = new Thickness(0);
            var d = cell.Column as DataGridTemplateColumn;
            var p = d.CellTemplate;
            if (ItemSource != null)
            {
                var ds = p.LoadContent() as ItemsControl;
                ds.SetValue(ItemsControl.ItemsSourceProperty, (ItemSource as List<DDL>)[0].TestType);
                return ds;
            }
            return null;
          
        }
    }
    public class DataList
    {
        public string SchoolName { get; set; }
        public List<DDL> List { get; set; }
    }
    public class DDL
    {
        public string RequestName { get; set; }
        public List<int> RequestNumList { get; set; }
        public List<string> TestType { get; set; }
    }

    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        List<DataList> GetDataLists = new List<DataList>();
        public MainWindow()
        {
            InitializeComponent();
            
            Init();
            Create();
        }
        private void Create()
        {
            this.DG.ItemsSource = GetDataLists;
            for (var i = 0; i < GetDataLists.Count; i++)
                Add(i);
        }

        private void Add(int i)
        {
            var clm = this.DG.Columns;
            var b = new DataNewColumn();
            b.ItemSource = GetDataLists[i].List;
            b.CellTemplate = this.FindResource("CDT") as DataTemplate;
            b.HeaderStyle = this.FindResource("s1") as Style;                                                         
            clm.Add(b);
        }

        private void Init()
        {
            Random random = new Random();
            for (var O = 0; O < 5; O++)
            {
                List<string> testtpyelist = new List<string>();
                List<int> requestnumlist = new List<int>();
                string requestname = "要求" + O.ToString();
                var d = random.Next(1, 10);
                for (var p = 0; p < d; p++)
                {
                    requestnumlist.Add(p);
                    testtpyelist.Add((p % 2 == 0) ? " " : "低");
                }
                var k = new DDL();
                k.TestType = testtpyelist;
                k.RequestNumList = requestnumlist;
                k.RequestName = requestname;

                var l = "大学  NO." + O.ToString();
                var t = new List<DDL>();
                t.Add(k);
                GetDataLists.Add(new DataList() { SchoolName = l, List = t });
            }
        }
    }
}

以上是关于WPF DataGrid表头合并且动态添加列的主要内容,如果未能解决你的问题,请参考以下文章

WPF Datagrid合并表头的思路

WPF的DataGrid怎么实现多行表头

wpf datagrid 多行表头

DataGrid如何显示双层表头,合并列头

vue中 表头th 合并单元格,且表格列数不定的动态渲染方法

vue中 表头 th 合并单元格,且表格列数不定的动态渲染方法