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 }); } } } }