• 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模板数据的配置,实现数表格头部的合并和数据显示。

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

    点击此处下载源码

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

  • 相关阅读:
    2020.10.23 19级training 补题报告
    2020.10.17 天梯赛练习 补题报告
    2020.10.16 19级training 补题报告
    2020.10.9 19级training 补题报告
    2020.10.10 天梯赛练习 补题报告
    2020.10.3 天梯赛练习 补题报告
    2020.10.2 19级training 补题报告
    第十届山东省ACM省赛复现补题报告
    VVDI Key Tool Plus Adds VW Passat 2015 Key via OBD
    Xhorse VVDI Prog Software V5.0.3 Adds Many MCUs
  • 原文地址:https://www.cnblogs.com/ligl/p/10289166.html
Copyright © 2020-2023  润新知