更正:
如果保留datagrid最后一行,则需要在 GenerateElement方法中判断dataitem是否为{newitemplaceholder}的字符串
重新更正为:
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&&dataItem.ToString()!= "{NewItemPlaceholder}")
{
var ds = p.LoadContent() as ItemsControl;
ds.SetValue(ItemsControl.ItemsSourceProperty, (ItemSource as List<DDL>)[0].BL);
return ds;
}
return base.GenerateElement(cell, dataItem);
}
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 });
}
}
}
}