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 = "破損及不良的原因,采用何種方法進行\r;修理。工作人員及車站值班員簽字" });

            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模板數據的配置,實現數表格頭部的合並和數據顯示。

還有一種稍微復雜表格頭的合並,目前是列合並,可能存在行和列同時合並,已經有思路還未驗證是否可行,由於項目暫未用到不花費時間研究,園友有需要就在下方留言。

點擊此處下載源碼

 合並行的已經實現:效果如下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM