• WPF DataGridTable


    由于项目要显示表头合并,而数据源列随时变更,又不想重复的画表格,就实现动态数据(dynamic)绑定和配置数据列模板的方式

    编辑DataGridColumnHeader样式实现表头合并:效果如下

    实现思路:

    在表头中插入一个Grid,Grid列跟HeaderColmun列数相等,并关联HeaderColmun的SizeChanged事件,Colmun列大小发生变化时,合并的头模板也会跟着移动。

     <Grid x:Name="PART_ColumnHeadersPresenter_Grid"
                                      Height="30"
                                      ShowGridLines="False">
                                </Grid>
       Dictionary<DataGridColumnHeader, ColumnDefinition> dictCols = new Dictionary<DataGridColumnHeader, ColumnDefinition>();
    
            private void DataGridTitleSpan_Loaded(object sender, RoutedEventArgs e)
            {
                var hdCols = WPFVisualTreeHelper.GetChildByName<DataGridColumnHeadersPresenter>(this, "PART_ColumnHeadersPresenter");
                var grid = WPFVisualTreeHelper.GetChildByName<Grid>(this, "PART_ColumnHeadersPresenter_Grid");
                if (grid == null)
                {
                    return;
                }
                //grid.Visibility = Visibility.Collapsed;
                //if (DataSouceGridHeaderColTemplate == null || DataSouceGridHeaderColTemplate.Count == 0)
                //{
                //    grid.Visibility = Visibility.Collapsed;
                //}
                var hdItem = WPFVisualTreeHelper.FindVisualChild<DataGridCellsPanel>(hdCols);
                var header = hdItem.FirstOrDefault();
                if (header != null)
                {
                    foreach (var item in header.Children)
                    {
                        var vHd = item as DataGridColumnHeader;
                        vHd.SizeChanged += VHd_SizeChanged;
                        ColumnDefinition rd = new ColumnDefinition();
                        rd.Width = new GridLength(vHd.ActualWidth, GridUnitType.Pixel);
                        grid.ColumnDefinitions.Add(rd);
                        dictCols[vHd] = rd;
                    }
                }
                GenerateHeader(DataSouceGridHeaderColTemplate, grid);
            }
    
            private void VHd_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                var vHd = sender as DataGridColumnHeader;
                if (dictCols.ContainsKey(vHd))
                {
                    dictCols[vHd].Width = new GridLength(vHd.ActualWidth, GridUnitType.Pixel);
                }
            }

    下面是完整的HeaderColmun列模板

    <Style x:Key="DataGridColumnHeaderStyle_Colspan"
               TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="VerticalContentAlignment"
                    Value="Center" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                        <!--<Grid>
                            <Themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}"
                                                         BorderThickness="{TemplateBinding BorderThickness}"
                                                         Background="{TemplateBinding Background}"
                                                         IsClickable="{TemplateBinding CanUserSort}"
                                                         IsPressed="{TemplateBinding IsPressed}"
                                                         IsHovered="{TemplateBinding IsMouseOver}"
                                                         Padding="{TemplateBinding Padding}"
                                                         SortDirection="{TemplateBinding SortDirection}"
                                                         SeparatorBrush="{TemplateBinding SeparatorBrush}"
                                                         SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  RecognizesAccessKey="True"
                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                            </Themes:DataGridHeaderBorder>
                            <Thumb x:Name="PART_LeftHeaderGripper"
                                   HorizontalAlignment="Left"
                                   Style="{StaticResource ColumnHeaderGripperStyle}" />
                            <Thumb x:Name="PART_RightHeaderGripper"
                                   HorizontalAlignment="Right"
                                   Style="{StaticResource ColumnHeaderGripperStyle}" />
                        </Grid>-->
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Border BorderBrush="{Binding BorderBrush,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                    Padding="{TemplateBinding Padding}"
                                    BorderThickness="0 0 0 1"
                                    Grid.Row="0"
                                    Visibility="{Binding Path=ColspanVisibility,RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
                                <Grid x:Name="PART_ColumnHeadersPresenter_Grid"
                                      Height="30"
                                      ShowGridLines="False">
                                </Grid>
                            </Border>
                            <Grid Grid.Row="1">
                                <Themes:DataGridHeaderBorder BorderBrush="{Binding BorderBrush,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                                             BorderThickness="0 0 1 1"
                                                             Background="Transparent"
                                                             IsClickable="{TemplateBinding CanUserSort}"
                                                             IsPressed="{TemplateBinding IsPressed}"
                                                             IsHovered="{TemplateBinding IsMouseOver}"
                                                             Padding="{TemplateBinding Padding}"
                                                             SortDirection="{TemplateBinding SortDirection}"
                                                             SeparatorBrush="{TemplateBinding SeparatorBrush}"
                                                             SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                    <ContentPresenter HorizontalAlignment="{Binding HorizontalContentAlignment,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                                      RecognizesAccessKey="True"
                                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                </Themes:DataGridHeaderBorder>
                                <Thumb x:Name="PART_LeftHeaderGripper"
                                       HorizontalAlignment="Left"
                                       Style="{StaticResource ColumnHeaderGripperStyle}" />
                                <Thumb x:Name="PART_RightHeaderGripper"
                                       HorizontalAlignment="Right"
                                       Style="{StaticResource ColumnHeaderGripperStyle}" />
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

    关键代码如下:

    显示的View Xaml和Code

    <UserControl x:Class="YunTong46View.Usr_TestDataGridTableView"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                 xmlns:local="clr-namespace:YunTong46View"
                 mc:Ignorable="d"
                 d:DesignHeight="300"
                 d:DesignWidth="300">
        <UserControl.Resources>
            <ResourceDictionary Source="Themes/DataGridStyle.xaml">
            </ResourceDictionary>
        </UserControl.Resources>
        <StackPanel>
            <StackPanel  Margin="20 15 20 10">
                <TextBlock Text="出现滚动条:数据绑定"
                           Foreground="Red"
                           FontSize="20"></TextBlock>
                <local:DataGridTitleSpan   x:Name="dataGridTitle2"
                                           Width="500"
                                           Height="200"
                                           VerticalAlignment="Top"
                                           HorizontalAlignment="Left"
                                           ScrollViewer.HorizontalScrollBarVisibility="Visible"
                                           ScrollViewer.VerticalScrollBarVisibility="Visible"
                                           DataSouceGridHeaderColTemplate="{Binding Headers0}"
                                           ItemsSource="{Binding DataSource}">
                </local:DataGridTitleSpan>
            </StackPanel>
            <StackPanel  Margin="20 10">
                <TextBlock Text="dynamic动态类数据绑定不支持排序"
                           Foreground="Red"
                           FontSize="20"></TextBlock>
                <local:DataGridTitleSpan   x:Name="dataGridTitle"
                                           Height="200"
                                           ScrollViewer.HorizontalScrollBarVisibility="Visible"
                                           ScrollViewer.VerticalScrollBarVisibility="Visible"
                                           DataSouceGridHeaderColTemplate="{Binding Headers0}">
                </local:DataGridTitleSpan>
            </StackPanel>
    
            <StackPanel  Margin="20 10">
                <TextBlock Text="引用样式"
                           Foreground="Red"
                           FontSize="20"></TextBlock>
                <DataGrid    x:Name="dataGrid"
                             Height="200"
                             Style="{DynamicResource DataGridStyle_Colspan}"
                             ItemsSource="{Binding DataSource}"
                             Visibility="Visible">
                </DataGrid>
            </StackPanel>
    
            <StackPanel  Margin="20 10">
                <TextBlock Text="原生DataGrid"
                           Foreground="Red"
                           FontSize="20"></TextBlock>
                <DataGrid    x:Name="dataGrid2"
                             Height="200"
                             BorderBrush="Blue"
                             AutoGenerateColumns="False"
                             HorizontalGridLinesBrush="Blue"
                             VerticalGridLinesBrush="Blue"
                             ItemsSource="{Binding DataSource}">
                </DataGrid>
            </StackPanel>
        </StackPanel>
    </UserControl>
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    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;
    
    namespace YunTong46View
    {
        /// <summary>
        /// Usr_YunTong46MainView.xaml 的交互逻辑
        /// </summary>
        public partial class Usr_TestDataGridTableView : UserControl
        {
            ViewMode viewMode = new ViewMode();
            public Usr_TestDataGridTableView()
            {
                InitializeComponent();
                viewMode.Init();
                this.DataContext = viewMode;
                SetHeaderTemplates(dataGridTitle, viewMode.Headers1);
                SetHeaderTemplates(dataGridTitle2, viewMode.Headers1);
                SetHeaderTemplates(dataGrid, viewMode.Headers1);
                SetHeaderTemplates(dataGrid2, viewMode.Headers1);
                this.Loaded += Usr_YunTong46MainView_Loaded;
            }
    
            private void Usr_YunTong46MainView_Loaded(object sender, RoutedEventArgs e)
            {
                var json = JsonHelper.SerializeObject(viewMode.DataSource);
                var dyDatas = JsonHelper.DeserializeObject<dynamic>(json);
                dataGridTitle.ItemsSource = dyDatas;
            }
    
            private void SetHeaderTemplates(DataGrid dataGrid, List<HeaderTemplate> headers)
            {
                foreach (var item in headers)
                {
                    var col = new DataGridTextColumn();
                    col.Header = item.HeaderName;
                    var bind = new Binding();
                    bind.Path = new PropertyPath(item.PropertyName);
                    if (!string.IsNullOrEmpty(item.PropertyFormat))
                    {
                        //bind.StringFormat = "{}{0:" + item.PropertyFormat + "}}";
                        bind.StringFormat = item.PropertyFormat.Trim();
                    }
                    col.Binding = bind;
                    DataGridLengthUnitType unType = DataGridLengthUnitType.Auto;
                    double width = 0;
                    if (item.ColmunUnitType == "p")
                    {
                        unType = DataGridLengthUnitType.Pixel;
                        width = item.ColmunWidth;
                    }
                    else if (item.ColmunUnitType == "s")
                    {
                        unType = DataGridLengthUnitType.Star;
                        width = item.ColmunWidth;
                    }
                    if (width < 0)
                    {
                        width = 0;
                    }
                    col.Width = new DataGridLength(width, unType);
                    dataGrid.Columns.Add(col);
                }
            }
        }
        public class ViewMode
        {
            private List<HeaderTemplate> _headers0 = new List<HeaderTemplate>();
            private List<HeaderTemplate> _headers1 = new List<HeaderTemplate>();
            private List<DataModel> _dataSource = new List<DataModel>();
    
            public List<HeaderTemplate> Headers0
            {
                get
                {
                    return _headers0;
                }
    
                set
                {
                    _headers0 = value;
                }
            }
    
            public List<HeaderTemplate> Headers1
            {
                get
                {
                    return _headers1;
                }
    
                set
                {
                    _headers1 = value;
                }
            }
    
            public List<DataModel> DataSource
            {
                get
                {
                    return _dataSource;
                }
    
                set
                {
                    _dataSource = value;
                }
            }
    
            public void Init()
            {
                _headers0.Add(new HeaderTemplate() { ColmunIndex = 0, ColmunSpan = 4, HeaderName = "故障登记时间及状态" });
                _headers0.Add(new HeaderTemplate() { ColmunIndex = 0, ColmunSpan = 4, HeaderName = "通知时间及通知方法" });
                _headers0.Add(new HeaderTemplate() { ColmunIndex = 0, ColmunSpan = 3, HeaderName = "到达时间及签名" });
                _headers0.Add(new HeaderTemplate() { ColmunIndex = 0, ColmunSpan = 3, HeaderName = "消除不良及破损后的时间和方法" });
    
    
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 0, ColmunSpan = 0, PropertyName = "GZDT", PropertyFormat = "MM-dd", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "月日" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 1, ColmunSpan = 0, PropertyName = "GZDT", PropertyFormat = "HH:mm", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "时分" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 2, ColmunSpan = 0, PropertyName = "GZDeviceName", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "设备名称" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 3, ColmunSpan = 0, PropertyName = "GZStatus", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "故障状态" });
    
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 4, ColmunSpan = 0, PropertyName = "TZDW", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "通知单位" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 5, ColmunSpan = 0, PropertyName = "TZDT", PropertyFormat = "MM-dd", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "月日" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 6, ColmunSpan = 0, PropertyName = "TZDT", PropertyFormat = "HH:mm", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "时分" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 7, ColmunSpan = 0, PropertyName = "TZFF", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "通知方法" });
    
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 8, ColmunSpan = 0, PropertyName = "DDDT", PropertyFormat = "MM-dd", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "月日" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 9, ColmunSpan = 0, PropertyName = "DDDT", PropertyFormat = "HH:mm", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "时分" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 10, ColmunSpan = 0, PropertyName = "DDQM", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "该段工作人员到达后签名" });
    
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 11, ColmunSpan = 0, PropertyName = "BLDT", PropertyFormat = "MM-dd", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "月日" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 12, ColmunSpan = 0, PropertyName = "BLDT", PropertyFormat = "HH:mm", ColmunUnitType = "a", ColmunWidth = 1, HeaderName = "时分" });
                _headers1.Add(new HeaderTemplate() { ColmunIndex = 13, ColmunSpan = 0, PropertyName = "BLTEXT", ColmunUnitType = "s", ColmunWidth = 10, HeaderName = "破损及不良的原因,采用何种方法进行
    ;修理。工作人员及车站值班员签字" });
    
                for (int i = 0; i < 10; i++)
                {
                    DataModel model = new DataModel();
                    model.DDDT = DateTime.Now.AddMinutes(-1);
                    model.GZDT = model.DDDT;
                    model.TZDT = model.DDDT;
                    model.BLDT = model.DDDT;
                    model.GZDeviceName = "故障设备名称" + i.ToString();
                    model.GZStatus = "故障状态" + i.ToString();
                    model.TZDW = "通知单位" + i.ToString();
                    model.TZFF = "通知方法" + i.ToString();
                    model.DDQM = "到达签名" + i.ToString();
                    model.BLTEXT = "不良内容" + i.ToString();
                    _dataSource.Add(model);
                }
            }
        }
    
        public class DataModel
        {
            public DateTime GZDT { set; get; }
    
            public string GZDeviceName { set; get; }
    
            public string GZStatus { set; get; }
    
            public DateTime TZDT { set; get; }
    
            public string TZDW { set; get; }
    
            public string TZFF { set; get; }
    
            /// <summary>
            /// 到达时间
            /// </summary>
            public DateTime DDDT { set; get; }
    
            public string DDQM { set; get; }
    
            public DateTime BLDT { set; get; }
    
            public string BLTEXT { set; get; }
        }
    }
    View Code

    DataTable样式和Code

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">
        <Style x:Key="DataGridRowStyle_ColSpan"
               TargetType="{x:Type DataGridRow}">
            <Setter Property="Background"
                    Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
            <Setter Property="SnapsToDevicePixels"
                    Value="true" />
            <Setter Property="Validation.ErrorTemplate"
                    Value="{x:Null}" />
            <Setter Property="ValidationErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <TextBlock Foreground="Red"
                                   Margin="2,0,0,0"
                                   Text="!"
                                   VerticalAlignment="Center" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridRow}">
                        <Border x:Name="DGR_Border"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Background="{TemplateBinding Background}"
                                SnapsToDevicePixels="True">
                            <SelectiveScrollingGrid>
                                <SelectiveScrollingGrid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                </SelectiveScrollingGrid.ColumnDefinitions>
                                <SelectiveScrollingGrid.RowDefinitions>
                                    <RowDefinition Height="*" />
                                    <RowDefinition Height="Auto" />
                                </SelectiveScrollingGrid.RowDefinitions>
                                <Border Grid.Column="1"
                                        BorderThickness="1 0 0 0"
                                        BorderBrush="{Binding BorderBrush,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}">
                                    <DataGridCellsPresenter ItemsPanel="{TemplateBinding ItemsPanel}"
                                                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                                </Border>
                                <DataGridDetailsPresenter Grid.Column="1"
                                                          Grid.Row="1"
                                                          SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                                          Visibility="{TemplateBinding DetailsVisibility}" />
                                <!--隐藏左侧行号-->
                                <DataGridRowHeader Grid.RowSpan="2"
                                                   SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
                                                   Visibility="Collapsed" />
                            </SelectiveScrollingGrid>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <Trigger Property="IsNewItem"
                         Value="True">
                    <Setter Property="Margin"
                            Value="{Binding NewItemMargin, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                </Trigger>
                <Trigger Property="IsSelected"
                         Value="True">
                    <Setter Property="Background"
                            Value="#FFE8C91A" />
                    <Setter Property="Foreground"
                            Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>
        <Style x:Key="DataGridCellStyle_Colspan"
               TargetType="{x:Type DataGridCell}">
            <Setter Property="FontSize"
                    Value="16" />
            <Setter Property="HorizontalContentAlignment"
                    Value="Center"></Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridCell}">
                        <!--<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                          VerticalAlignment="Center"
                                          HorizontalAlignment="Center" />-->
                        <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
    
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <!--<Style.Triggers>
                            <Trigger Property="IsSelected"
                                     Value="True">
                                <Setter Property="Background"
                                        Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                                <Setter Property="Foreground"
                                        Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
                                <Setter Property="BorderBrush"
                                        Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                            </Trigger>
                            <Trigger Property="IsMouseOver"
                                     Value="True">
                                <Setter Property="Background"
                                        Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
                            </Trigger>
                            <Trigger Property="IsKeyboardFocusWithin"
                                     Value="True">
                                <Setter Property="BorderBrush"
                                        Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}" />
                            </Trigger>
                            <Trigger Property="IsSelected"
                                     Value="True">
                                <Setter Property="Foreground"
                                        Value="Black" />
                            </Trigger>
                        </Style.Triggers>-->
        </Style>
        <BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />
        <!--<Style x:Key="RowHeaderGripperStyle"
               TargetType="{x:Type Thumb}">
            <Setter Property="Height"
                    Value="8" />
            <Setter Property="Background"
                    Value="Transparent" />
            <Setter Property="Cursor"
                    Value="SizeNS" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border Background="{TemplateBinding Background}"
                                Padding="{TemplateBinding Padding}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>-->
        <Style x:Key="DataGridRowHeaderStyle_Colspan"
               TargetType="{x:Type DataGridRowHeader}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridRowHeader}">
                        <Grid>
                            <Themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}"
                                                         BorderThickness="{TemplateBinding BorderThickness}"
                                                         Background="{TemplateBinding Background}"
                                                         IsPressed="{TemplateBinding IsPressed}"
                                                         IsHovered="{TemplateBinding IsMouseOver}"
                                                         IsSelected="{TemplateBinding IsRowSelected}"
                                                         Orientation="Horizontal"
                                                         Padding="{TemplateBinding Padding}"
                                                         SeparatorBrush="{TemplateBinding SeparatorBrush}"
                                                         SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                <StackPanel Orientation="Horizontal">
                                    <ContentPresenter RecognizesAccessKey="True"
                                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                      VerticalAlignment="Center" />
                                    <Control SnapsToDevicePixels="false"
                                             Template="{Binding ValidationErrorTemplate, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}"
                                             Visibility="{Binding (Validation.HasError), Converter={StaticResource bool2VisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
                                </StackPanel>
                            </Themes:DataGridHeaderBorder>
                            <!--<Thumb x:Name="PART_TopHeaderGripper"
                                   Style="{StaticResource RowHeaderGripperStyle}"
                                   VerticalAlignment="Top" />
                            <Thumb x:Name="PART_BottomHeaderGripper"
                                   Style="{StaticResource RowHeaderGripperStyle}"
                                   VerticalAlignment="Bottom" />-->
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="ColumnHeaderGripperStyle"
               TargetType="{x:Type Thumb}">
            <Setter Property="Width"
                    Value="8" />
            <Setter Property="Background"
                    Value="Transparent" />
            <Setter Property="Cursor"
                    Value="SizeWE" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border Background="{TemplateBinding Background}"
                                Padding="{TemplateBinding Padding}" />
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="DataGridColumnHeaderStyle_Colspan"
               TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="VerticalContentAlignment"
                    Value="Center" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                        <!--<Grid>
                            <Themes:DataGridHeaderBorder BorderBrush="{TemplateBinding BorderBrush}"
                                                         BorderThickness="{TemplateBinding BorderThickness}"
                                                         Background="{TemplateBinding Background}"
                                                         IsClickable="{TemplateBinding CanUserSort}"
                                                         IsPressed="{TemplateBinding IsPressed}"
                                                         IsHovered="{TemplateBinding IsMouseOver}"
                                                         Padding="{TemplateBinding Padding}"
                                                         SortDirection="{TemplateBinding SortDirection}"
                                                         SeparatorBrush="{TemplateBinding SeparatorBrush}"
                                                         SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                                  RecognizesAccessKey="True"
                                                  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                  VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                            </Themes:DataGridHeaderBorder>
                            <Thumb x:Name="PART_LeftHeaderGripper"
                                   HorizontalAlignment="Left"
                                   Style="{StaticResource ColumnHeaderGripperStyle}" />
                            <Thumb x:Name="PART_RightHeaderGripper"
                                   HorizontalAlignment="Right"
                                   Style="{StaticResource ColumnHeaderGripperStyle}" />
                        </Grid>-->
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"></RowDefinition>
                                <RowDefinition Height="*"></RowDefinition>
                            </Grid.RowDefinitions>
                            <Border BorderBrush="{Binding BorderBrush,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                    Padding="{TemplateBinding Padding}"
                                    BorderThickness="0 0 0 1"
                                    Grid.Row="0"
                                    Visibility="{Binding Path=ColspanVisibility,RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
                                <Grid x:Name="PART_ColumnHeadersPresenter_Grid"
                                      Height="30"
                                      ShowGridLines="False">
                                </Grid>
                            </Border>
                            <Grid Grid.Row="1">
                                <Themes:DataGridHeaderBorder BorderBrush="{Binding BorderBrush,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                                             BorderThickness="0 0 1 1"
                                                             Background="Transparent"
                                                             IsClickable="{TemplateBinding CanUserSort}"
                                                             IsPressed="{TemplateBinding IsPressed}"
                                                             IsHovered="{TemplateBinding IsMouseOver}"
                                                             Padding="{TemplateBinding Padding}"
                                                             SortDirection="{TemplateBinding SortDirection}"
                                                             SeparatorBrush="{TemplateBinding SeparatorBrush}"
                                                             SeparatorVisibility="{TemplateBinding SeparatorVisibility}">
                                    <ContentPresenter HorizontalAlignment="{Binding HorizontalContentAlignment,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGrid}}}"
                                                      RecognizesAccessKey="True"
                                                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                                </Themes:DataGridHeaderBorder>
                                <Thumb x:Name="PART_LeftHeaderGripper"
                                       HorizontalAlignment="Left"
                                       Style="{StaticResource ColumnHeaderGripperStyle}" />
                                <Thumb x:Name="PART_RightHeaderGripper"
                                       HorizontalAlignment="Right"
                                       Style="{StaticResource ColumnHeaderGripperStyle}" />
                            </Grid>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
        <Style x:Key="DataGridStyle_Colspan"
               TargetType="{x:Type DataGrid}">
            <Setter Property="Background"
                    Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
            <Setter Property="Foreground"
                    Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
            <Setter Property="BorderBrush"
                    Value="#FF688CAF" />
            <Setter Property="HorizontalContentAlignment"
                    Value="Center"></Setter>
            <Setter Property="BorderThickness"
                    Value="0" />
            <Setter Property="RowDetailsVisibilityMode"
                    Value="VisibleWhenSelected" />
            <Setter Property="ScrollViewer.CanContentScroll"
                    Value="true" />
            <Setter Property="ScrollViewer.PanningMode"
                    Value="Both" />
            <Setter Property="Stylus.IsFlicksEnabled"
                    Value="False" />
            <Setter Property="CanUserAddRows"
                    Value="False" />
            <Setter Property="BorderBrush"
                    Value="Blue">
            </Setter>
            <Setter Property="HorizontalGridLinesBrush"
                    Value="Blue">
            </Setter>
            <Setter Property="VerticalGridLinesBrush"
                    Value="Blue">
            </Setter>
            <Setter Property="AutoGenerateColumns"
                    Value="False">
            </Setter>
            <Setter Property="TextBlock.TextAlignment"
                    Value="Center">
            </Setter>
            <Setter Property="RowHeaderStyle"
                    Value="{StaticResource DataGridRowHeaderStyle_Colspan}">
            </Setter>
            <Setter Property="RowStyle"
                    Value="{StaticResource DataGridRowStyle_ColSpan}">
            </Setter>
            <Setter Property="ColumnHeaderStyle"
                    Value="{StaticResource DataGridColumnHeaderStyle_Colspan}">
            </Setter>
            <Setter Property="CellStyle"
                    Value="{StaticResource DataGridCellStyle_Colspan}">
            </Setter>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type DataGrid}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                Background="{TemplateBinding Background}"
                                Padding="{TemplateBinding Padding}"
                                SnapsToDevicePixels="True"
                                x:Name="bd_Out">
                            <ScrollViewer x:Name="DG_ScrollViewer"
                                          Focusable="false">
                                <ScrollViewer.Template>
                                    <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                        <Grid>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition Width="Auto" />
                                                <ColumnDefinition Width="*" />
                                                <ColumnDefinition Width="Auto" />
                                            </Grid.ColumnDefinitions>
                                            <Grid.RowDefinitions>
                                                <RowDefinition Height="Auto" />
                                                <RowDefinition Height="*" />
                                                <RowDefinition Height="Auto" />
                                            </Grid.RowDefinitions>
                                            <Button Command="{x:Static DataGrid.SelectAllCommand}"
                                                    Focusable="false"
                                                    Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}"
                                                    Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
                                                    Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                            <Border BorderThickness="1 1 1 0"
                                                    Margin="-1 0 0 0"
                                                    BorderBrush="{Binding BorderBrush,ElementName=bd_Out}"
                                                    Grid.Column="1">
                                                <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"
                                                                                Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                            </Border>
                                            <ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
                                                                    CanContentScroll="{TemplateBinding CanContentScroll}"
                                                                    Grid.ColumnSpan="2"
                                                                    Grid.Row="1" />
                                            <ScrollBar x:Name="PART_VerticalScrollBar"
                                                       Grid.Column="2"
                                                       Maximum="{TemplateBinding ScrollableHeight}"
                                                       Orientation="Vertical"
                                                       Grid.Row="1"
                                                       Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
                                                       Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                                                       ViewportSize="{TemplateBinding ViewportHeight}" />
                                            <Grid Grid.Column="1"
                                                  Grid.Row="2">
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                                    <ColumnDefinition Width="*" />
                                                </Grid.ColumnDefinitions>
                                                <ScrollBar x:Name="PART_HorizontalScrollBar"
                                                           Grid.Column="1"
                                                           Maximum="{TemplateBinding ScrollableWidth}"
                                                           Orientation="Horizontal"
                                                           Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
                                                           Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                                                           ViewportSize="{TemplateBinding ViewportWidth}" />
                                            </Grid>
                                        </Grid>
                                    </ControlTemplate>
                                </ScrollViewer.Template>
                                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </ScrollViewer>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <MultiTrigger>
                    <MultiTrigger.Conditions>
                        <Condition Property="IsGrouping"
                                   Value="true" />
                        <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping"
                                   Value="false" />
                    </MultiTrigger.Conditions>
                    <Setter Property="ScrollViewer.CanContentScroll"
                            Value="false" />
                </MultiTrigger>
            </Style.Triggers>
        </Style>
    </ResourceDictionary>
    View Code
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Controls.Primitives;
    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;
    
    namespace YunTong46View
    {
        /// <summary>
        /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
        ///
        /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:YunTong46View"
        ///
        ///
        /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
        /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 
        /// 元素中: 
        ///
        ///     xmlns:MyNamespace="clr-namespace:YunTong46View;assembly=YunTong46View"
        ///
        /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
        /// 并重新生成以避免编译错误: 
        ///
        ///     在解决方案资源管理器中右击目标项目,然后依次单击
        ///     “添加引用”->“项目”->[浏览查找并选择此项目]
        ///
        ///
        /// 步骤 2)
        /// 继续操作并在 XAML 文件中使用控件。
        ///
        ///     <MyNamespace:DataGridTitleSpan/>
        ///
        /// </summary>
        public class DataGridTitleSpan : DataGrid
        {
            ResourceDictionary rs = new ResourceDictionary();
            static DataGridTitleSpan()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(DataGridTitleSpan), new FrameworkPropertyMetadata(typeof(DataGridTitleSpan)));
            }
    
            public DataGridTitleSpan() : base()
            {
                rs.Source = new Uri("/YunTong46View;component/Themes/DataGridStyle.xaml", UriKind.Relative);
                //RowHeaderStyle = rs["DataGridRowHeaderStyle_Colspan"] as Style;
                //RowStyle = rs["DataGridRowStyle_ColSpan"] as Style;
                //ColumnHeaderStyle = rs["DataGridColumnHeaderStyle_Colspan"] as Style;
                var style = rs["DataGridStyle_Colspan"] as Style;
                this.Style = style;
                this.Loaded += DataGridTitleSpan_Loaded;
            }
    
            public List<HeaderTemplate> DataSouceGridHeaderColTemplate
            {
                get { return (List<HeaderTemplate>)GetValue(DataSouceGridHeaderColTemplateProperty); }
                set { SetValue(DataSouceGridHeaderColTemplateProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for DataSouceGridHeaderTemplate.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty DataSouceGridHeaderColTemplateProperty =
                DependencyProperty.Register("DataSouceGridHeaderColTemplate", typeof(List<HeaderTemplate>), typeof(DataGridTitleSpan), new PropertyMetadata(null));
    
    
    
            public Visibility ColspanVisibility
            {
                get { return (Visibility)GetValue(ColspanVisibilityProperty); }
                set { SetValue(ColspanVisibilityProperty, value); }
            }
    
            // Using a DependencyProperty as the backing store for ColspanVisibility.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty ColspanVisibilityProperty =
                DependencyProperty.Register("ColspanVisibility", typeof(Visibility), typeof(DataGridTitleSpan), new PropertyMetadata(Visibility.Visible));
    
    
            Dictionary<DataGridColumnHeader, ColumnDefinition> dictCols = new Dictionary<DataGridColumnHeader, ColumnDefinition>();
    
            private void DataGridTitleSpan_Loaded(object sender, RoutedEventArgs e)
            {
                var hdCols = WPFVisualTreeHelper.GetChildByName<DataGridColumnHeadersPresenter>(this, "PART_ColumnHeadersPresenter");
                var grid = WPFVisualTreeHelper.GetChildByName<Grid>(this, "PART_ColumnHeadersPresenter_Grid");
                if (grid == null)
                {
                    return;
                }
                if (DataSouceGridHeaderColTemplate == null || DataSouceGridHeaderColTemplate.Count == 0)
                {
                    (grid.Parent as Border).Visibility = Visibility.Collapsed;
                    //ColspanVisibility = Visibility.Collapsed;
                    return;
                }
                var hdItem = WPFVisualTreeHelper.FindVisualChild<DataGridCellsPanel>(hdCols);
                var header = hdItem.FirstOrDefault();
                if (header != null)
                {
                    foreach (var item in header.Children)
                    {
                        var vHd = item as DataGridColumnHeader;
                        vHd.SizeChanged += VHd_SizeChanged;
                        ColumnDefinition rd = new ColumnDefinition();
                        rd.Width = new GridLength(vHd.ActualWidth, GridUnitType.Pixel);
                        grid.ColumnDefinitions.Add(rd);
                        dictCols[vHd] = rd;
                    }
                }
                GenerateHeader(DataSouceGridHeaderColTemplate, grid);
            }
    
            private void VHd_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                var vHd = sender as DataGridColumnHeader;
                if (dictCols.ContainsKey(vHd))
                {
                    dictCols[vHd].Width = new GridLength(vHd.ActualWidth, GridUnitType.Pixel);
                }
            }
    
    
            private void GenerateHeader(List<HeaderTemplate> headers, Grid g)
            {
                int colIndex = 0;
                for (int i = 0; i < headers.Count; i++)
                {
                    var col = headers[i];
                    g.Children.Add(BigTitle(colIndex, col.ColmunSpan, col.HeaderName));
                    colIndex += (col.ColmunSpan + col.ColmunIndex);
                }
            }
    
            private UIElement BigTitle(int col, int colspan, string text)
            {
                var txb = new TextBlock();
                Border bd = new Border();
                bd.BorderThickness = new Thickness(0, 0, 1, 0);
                bd.BorderBrush = this.BorderBrush;
                //bd.Background = Brushes.Red;
                bd.Child = txb;
                txb.HorizontalAlignment = HorizontalAlignment.Center;
                txb.VerticalAlignment = VerticalAlignment.Center;
                txb.Text = text;
                Grid.SetColumn(bd, col);
                if (colspan > 0)
                {
                    Grid.SetColumnSpan(bd, colspan);
                }
                return bd;
            }
        }
    }
    View Code

    如果想修改表格颜色请设置下面三个Brush

      <Setter Property="BorderBrush"
                    Value="Blue">
            </Setter>
            <Setter Property="HorizontalGridLinesBrush"
                    Value="Blue">
            </Setter>
            <Setter Property="VerticalGridLinesBrush"
                    Value="Blue">
            </Setter>
    此功能有两个小问题:
    1.DataGridTitleSpan_Loaded捕获了DataGrid的列,所以不能在UserControl或者window的Load事件中SetHeaderTemplates,只能再构造函数中设置列。
    2.原本以为通过判断合并列的数据如果为空,那么自动隐藏Grid,但是不知道为什么不生效,只能通过依赖属性才能隐藏合并的头
     if (DataSouceGridHeaderColTemplate == null || DataSouceGridHeaderColTemplate.Count == 0)
                {
                    (grid.Parent as Border).Visibility = Visibility.Collapsed;
                    //ColspanVisibility = Visibility.Collapsed;
                    return;
                }

    该示例主要的目的通过HeaderTemplate模板数据的配置,实现数表格头部的合并和数据显示。

    还有一种稍微复杂表格头的合并,目前是列合并,可能存在行和列同时合并,已经有思路还未验证是否可行,由于项目暂未用到不花费时间研究,园友有需要就在下方留言。

    点击此处下载源码

     合并行的已经实现:效果如下

  • 相关阅读:
    java错误分析之junit测试错误(实验一)
    oracle逐步学习总结之oracle分页查询(基础三)
    OracleServer总结进阶之系统分析(进阶完结)
    QMS 的趨勢概述
    Python 類別 class 的繼承 Inheritance
    Python 面向導向語言 Object Oriented Programming Language
    Python 參考資源
    Dynamics 365-CRM又报看不懂的错误了
    Dynamics 365-为什么查到的Record的Id是Guid初始值
    Dynamics 365-如何下载新版本的Tools
  • 原文地址:https://www.cnblogs.com/ligl/p/10289166.html
Copyright © 2020-2023  润新知