尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

WPF DataGrid美化实战:从零打造专业级数据表格样式

WPF DataGrid美化实战:从零打造专业级数据表格样式 1. 项目概述一个可以直接“抄作业”的WPF DataGrid美化方案做WPF开发的朋友尤其是做上位机、MES、ERP这类需要展示大量数据的桌面应用时肯定都跟DataGrid控件打过交道。微软自带的DataGrid功能强大但那个默认的灰白格子界面实在是有点“朴素”直接用到项目里产品经理和客户看了大概率会摇头。网上虽然有很多美化教程但要么是零散的样式片段要么是依赖特定第三方控件库想要一个既美观、又独立、还能直接集成到现有项目中的完整解决方案往往需要自己花大量时间拼凑和调试。今天要分享的就是我基于一个实际项目打磨出来的一套非常精美、可直接复用的WPF DataGrid界面样式。这不仅仅是一个“皮肤”它更是一个快速学习WPF复杂布局和样式设计的实战例子。我把整个项目的全开源代码都整理好了你完全可以直接拿去用在你的项目里或者通过拆解它快速掌握如何打造专业级数据展示界面的核心技巧。无论是表头渐变、行颜色交替、鼠标悬浮高亮还是单元格模板定制、滚动条美化这里都提供了经过实战检验的实现方案。如果你正在为如何让DataGrid看起来更专业、更现代而烦恼那这个案例应该能给你一条清晰的路径。2. 整体设计思路从功能控件到视觉组件的蜕变2.1 核心需求解析DataGrid美化的常见痛点在动手设计之前我们先明确目标一个“精美”的DataGrid需要解决哪些默认样式的痛点根据我的经验主要集中在以下几点视觉层次单一默认样式缺乏层次感行与行、列与列之间区分度不够长时间浏览容易串行。交互反馈薄弱选中、悬浮的视觉效果不明显用户操作缺乏清晰的即时反馈。细节粗糙滚动条样式与整体风格不搭边框线条生硬字体和颜色搭配不协调缺乏现代感。定制化困难虽然DataGrid支持模板和样式但属性繁多嵌套复杂自己从头编写一个协调美观的完整样式成本很高。因此我们的设计思路不是简单地修改几个颜色而是将DataGrid视为一个由多个视觉部件表头、单元格、行、滚动条等组成的复合控件对每个部件进行系统性重塑并确保它们在一起工作时风格统一、交互和谐。2.2 技术方案选型纯Style与Template的威力为了实现高度定制化和保持项目轻量我选择了**完全基于WPF原生Style和ControlTemplate**的方案没有引入任何第三方UI控件库如MahApps.Metro, MaterialDesignInXaml等。这样做的好处非常明显零依赖代码拿到任何WPF项目中都能直接编译使用无需处理复杂的NuGet包引用和版本冲突。深度可控每一个像素、每一种状态Normal, MouseOver, Selected都可以精确控制实现真正意义上的“量身定制”。最佳学习素材通过解剖这个完整的样式你能最直观地学到WPF样式继承、模板绑定、触发器、视觉状态等核心概念的实际应用这是使用现成控件库无法比拟的。整个方案的核心是创建一个资源字典如CustomDataGridStyle.xaml在其中为DataGrid及其子部件DataGridCell,DataGridColumnHeader,DataGridRow等定义全新的Style和Template。我们将采用类似“设计系统”的思路先定义一套基础的颜色、笔刷和尺寸资源再在所有部件中引用它们确保视觉统一。3. 核心样式细节解析与实现要点3.1 色彩与视觉体系构建美观的界面始于一套协调的色彩方案。我建议不要在样式里直接写死颜色值如”#FF007ACC”而是定义一系列资源方便整体换肤。!-- 在Resources中定义颜色和笔刷 -- Color x:KeyPrimaryColor#FF007ACC/Color Color x:KeySecondaryColor#FF6C757D/Color Color x:KeyBackgroundLight#FFF8F9FA/Color Color x:KeyBackgroundDark#FFE9ECEF/Color Color x:KeyBorderColor#FFDEE2E6/Color Color x:KeyHoverColor#1A007ACC/Color !-- 主色的浅透明版 -- Color x:KeySelectedColor#33007ACC/Color !-- 主色的更浅透明版 -- SolidColorBrush x:KeyPrimaryBrush Color{StaticResource PrimaryColor}/ LinearGradientBrush x:KeyHeaderBackgroundBrush StartPoint0,0 EndPoint0,1 GradientStop Offset0 Color#FFFFFFFF/ GradientStop Offset1 Color{StaticResource BackgroundDark}/ /LinearGradientBrush为什么用透明色对于悬浮Hover和选中Selected状态使用带透明度的颜色叠加在原有背景上比直接替换为纯色视觉效果更柔和且能保留行背景交替AlternatingRowBackground的效果这是一个关键技巧。3.2 DataGrid 主体样式框架首先为DataGrid本身创建一个样式设置一些影响全局的属性并替换其模板以植入自定义的滚动条。Style TargetType{x:Type DataGrid} x:KeyCustomDataGridStyle Setter PropertyBackground ValueTransparent/ Setter PropertyBorderBrush Value{StaticResource BorderColorBrush}/ Setter PropertyBorderThickness Value1/ Setter PropertyRowDetailsVisibilityMode ValueVisibleWhenSelected/ Setter PropertyScrollViewer.CanContentScroll Valuetrue/ Setter PropertyScrollViewer.PanningMode ValueBoth/ Setter PropertyStylus.IsFlicksEnabled ValueFalse/ !-- 关键设置行高、网格线、交替行背景 -- Setter PropertyRowHeight Value32/ Setter PropertyGridLinesVisibility ValueNone/ !-- 我们用自己的边框 -- Setter PropertyHorizontalGridLinesBrush Value{StaticResource BorderColorBrush}/ Setter PropertyVerticalGridLinesBrush Value{StaticResource BorderColorBrush}/ Setter PropertyAlternationCount Value2/ Setter PropertyAlternatingRowBackground Value{StaticResource BackgroundDarkBrush}/ Setter PropertyHeadersVisibility ValueColumn/ !-- 通常只需要列头 -- Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type DataGrid} Border BorderBrush{TemplateBinding BorderBrush} BorderThickness{TemplateBinding BorderThickness} Background{TemplateBinding Background} Padding{TemplateBinding Padding} SnapsToDevicePixelsTrue ScrollViewer x:NameDG_ScrollViewer Focusablefalse ScrollViewer.Template ControlTemplate TargetType{x:Type ScrollViewer} Grid Grid.ColumnDefinitions ColumnDefinition WidthAuto/ ColumnDefinition Width*/ ColumnDefinition WidthAuto/ /Grid.ColumnDefinitions Grid.RowDefinitions RowDefinition HeightAuto/ RowDefinition Height*/ RowDefinition HeightAuto/ /Grid.RowDefinitions !-- 自定义滚动条位置 -- ScrollContentPresenter x:NamePART_ScrollContentPresenter Grid.Row1 Grid.Column1 Content{TemplateBinding Content} ContentTemplate{TemplateBinding ContentTemplate} CanContentScroll{TemplateBinding CanContentScroll} / !-- 水平滚动条 -- ScrollBar x:NamePART_HorizontalScrollBar OrientationHorizontal Grid.Row2 Grid.Column1 Maximum{TemplateBinding ScrollableWidth} ViewportSize{TemplateBinding ViewportWidth} Value{TemplateBinding HorizontalOffset} Visibility{TemplateBinding ComputedHorizontalScrollBarVisibility}/ !-- 垂直滚动条 -- ScrollBar x:NamePART_VerticalScrollBar OrientationVertical Grid.Row1 Grid.Column2 Maximum{TemplateBinding ScrollableHeight} ViewportSize{TemplateBinding ViewportHeight} Value{TemplateBinding VerticalOffset} Visibility{TemplateBinding ComputedVerticalScrollBarVisibility}/ /Grid /ControlTemplate /ScrollViewer.Template ItemsPresenter SnapsToDevicePixels{TemplateBinding SnapsToDevicePixels} / /ScrollViewer /Border /ControlTemplate /Setter.Value /Setter /Style注意在DataGrid的模板中嵌入ScrollViewer的模板是为了能同时美化水平和垂直滚动条。我们将滚动条单独放置在了Grid的特定单元格为后续给它们应用样式做好了准备。3.3 列标题DataGridColumnHeader美化列标题是DataGrid的“门面”一个精致的渐变背景和合适的鼠标交互能极大提升质感。Style TargetType{x:Type DataGridColumnHeader} x:KeyCustomColumnHeaderStyle Setter PropertyVerticalContentAlignment ValueCenter/ Setter PropertyHorizontalContentAlignment ValueCenter/ Setter PropertyHeight Value36/ Setter PropertyBackground Value{StaticResource HeaderBackgroundBrush}/ Setter PropertyBorderBrush Value{StaticResource BorderColorBrush}/ Setter PropertyBorderThickness Value0,0,1,1/ !-- 右和下边框 -- Setter PropertyForeground Value{StaticResource SecondaryColorBrush}/ Setter PropertyFontWeight ValueSemiBold/ Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type DataGridColumnHeader} Grid Border x:NameheaderBorder Background{TemplateBinding Background} BorderBrush{TemplateBinding BorderBrush} BorderThickness{TemplateBinding BorderThickness} Padding{TemplateBinding Padding} ContentPresenter HorizontalAlignment{TemplateBinding HorizontalContentAlignment} VerticalAlignment{TemplateBinding VerticalContentAlignment} SnapsToDevicePixels{TemplateBinding SnapsToDevicePixels}/ /Border Thumb x:NamePART_LeftHeaderGripper HorizontalAlignmentLeft/ Thumb x:NamePART_RightHeaderGripper HorizontalAlignmentRight/ /Grid ControlTemplate.Triggers !-- 鼠标悬浮效果 -- Trigger PropertyIsMouseOver ValueTrue Setter TargetNameheaderBorder PropertyBackground Setter.Value LinearGradientBrush StartPoint0,0 EndPoint0,1 GradientStop Offset0 Color#FFF0F7FF/ GradientStop Offset1 Color#FFD1E7FF/ /LinearGradientBrush /Setter.Value /Setter /Trigger !-- 按下效果 -- Trigger PropertyIsPressed ValueTrue Setter TargetNameheaderBorder PropertyBackground Value{StaticResource PrimaryBrush}/ Setter TargetNameheaderBorder PropertyForeground ValueWhite/ /Trigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter /Style实操心得列头的BorderThickness设置为”0,0,1,1″是为了在视觉上形成网格线。通常不需要左边框和上边框因为DataGrid的外边框和第一个列头的上边框会提供边界。通过触发器改变背景提供了清晰的交互反馈。PART_LeftHeaderGripper和PART_RightHeaderGripper这两个Thumb是用于调整列宽的必须保留但我们可以通过样式让它们不可见或仅在悬浮时显示。3.4 数据行DataGridRow与单元格DataGridCell样式行和单元格的样式决定了数据区域的阅读体验。核心是实现行交替背景、悬浮高亮和选中效果。!-- 数据行样式 -- Style TargetType{x:Type DataGridRow} x:KeyCustomDataGridRowStyle Setter PropertyBackground ValueTransparent/ Setter PropertySnapsToDevicePixels Valuetrue/ Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type DataGridRow} Border x:NameDGR_Border Background{TemplateBinding Background} BorderBrush{TemplateBinding BorderBrush} BorderThickness{TemplateBinding BorderThickness} SnapsToDevicePixelsTrue SelectiveScrollingGrid SelectiveScrollingGrid.ColumnDefinitions ColumnDefinition WidthAuto/ ColumnDefinition Width*/ /SelectiveScrollingGrid.ColumnDefinitions SelectiveScrollingGrid.RowDefinitions RowDefinition Height*/ RowDefinition HeightAuto/ /SelectiveScrollingGrid.RowDefinitions !-- 行详情和单元格呈现器 -- DataGridCellsPresenter Grid.Column1 ItemsPanel{TemplateBinding ItemsPanel} SnapsToDevicePixels{TemplateBinding SnapsToDevicePixels}/ DataGridDetailsPresenter Grid.Row1 Grid.Column1 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.RowSpan2 SelectiveScrollingGrid.SelectiveScrollingOrientationVertical Visibility{Binding RelativeSource{RelativeSource AncestorType{x:Type DataGrid}}, PathHeadersVisibility, Converter{x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter{x:Static DataGridHeadersVisibility.Row}}/ /SelectiveScrollingGrid /Border ControlTemplate.Triggers !-- 关键使用AlternationIndex实现交替行背景 -- Trigger PropertyItemsControl.AlternationIndex Value0 Setter PropertyBackground ValueTransparent/ /Trigger Trigger PropertyItemsControl.AlternationIndex Value1 Setter PropertyBackground Value{DynamicResource AlternatingRowBackgroundBrush}/ /Trigger !-- 鼠标悬浮效果使用半透明叠加 -- Trigger PropertyIsMouseOver ValueTrue Setter TargetNameDGR_Border PropertyBackground Setter.Value SolidColorBrush Color{StaticResource HoverColor}/ /Setter.Value /Setter /Trigger !-- 行选中效果 -- MultiTrigger MultiTrigger.Conditions Condition PropertyIsSelected ValueTrue/ /MultiTrigger.Conditions Setter TargetNameDGR_Border PropertyBackground Setter.Value SolidColorBrush Color{StaticResource SelectedColor}/ /Setter.Value /Setter /MultiTrigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter /Style !-- 数据单元格样式 -- Style TargetType{x:Type DataGridCell} x:KeyCustomDataGridCellStyle Setter PropertyBackground ValueTransparent/ Setter PropertyBorderBrush Value{StaticResource BorderColorBrush}/ Setter PropertyBorderThickness Value0,0,1,1/ !-- 右和下边框 -- Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type DataGridCell} Border x:NamecellBorder Background{TemplateBinding Background} BorderBrush{TemplateBinding BorderBrush} BorderThickness{TemplateBinding BorderThickness} SnapsToDevicePixelsTrue ContentPresenter x:NamecontentPresenter VerticalAlignment{TemplateBinding VerticalContentAlignment} HorizontalAlignment{TemplateBinding HorizontalContentAlignment} SnapsToDevicePixels{TemplateBinding SnapsToDevicePixels}/ /Border ControlTemplate.Triggers !-- 单元格获得焦点时的效果可编辑时 -- Trigger PropertyIsSelected ValueTrue Setter TargetNamecellBorder PropertyBorderBrush Value{StaticResource PrimaryBrush}/ Setter TargetNamecellBorder PropertyBorderThickness Value1/ /Trigger Trigger PropertyIsKeyboardFocusWithin ValueTrue Setter TargetNamecellBorder PropertyBorderBrush Value{StaticResource PrimaryBrush}/ /Trigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter Style.Triggers !-- 确保单元格在行选中时背景不被覆盖保持行的选中色 -- Trigger PropertyIsSelected ValueTrue Setter PropertyForeground Value{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}/ Setter PropertyBackground ValueTransparent/ /Trigger /Style.Triggers /Style重要提示这里有一个关键点即行背景和单元格背景的层级关系。我们让行的Trigger控制行的背景色悬浮、选中而单元格的背景始终保持Transparent。这样行的背景色才能透过单元格显示出来实现整行的视觉高亮。如果单元格设置了不透明的背景色就会盖住行的效果。3.5 滚动条ScrollBar样式美化默认的滚动条是操作系统主题样式与我们的自定义界面格格不入。美化滚动条能极大提升整体感。!-- 滚动条整体样式 -- Style TargetType{x:Type ScrollBar} Setter PropertyStylus.IsPressAndHoldEnabled Valuefalse/ Setter PropertyStylus.IsFlicksEnabled Valuefalse/ Setter PropertyBackground ValueTransparent/ Setter PropertyWidth Value10/ !-- 垂直滚动条宽度 -- Setter PropertyHeight Value10/ !-- 水平滚动条高度 -- Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type ScrollBar} Grid x:NameGridRoot Background{TemplateBinding Background} Grid.RowDefinitions RowDefinition MaxHeight18/ RowDefinition Height0.00001*/ RowDefinition MaxHeight18/ /Grid.RowDefinitions Grid.ColumnDefinitions ColumnDefinition MaxWidth18/ ColumnDefinition Width0.00001*/ ColumnDefinition MaxWidth18/ /Grid.ColumnDefinitions !-- 轨道 -- Border x:NameTrackBackground Grid.Row1 Grid.Column1 CornerRadius2 Background#10000000/ !-- 非常浅的灰色轨道 -- !-- 可拖动的滑块Thumb -- Track x:NamePART_Track Grid.Row1 Grid.Column1 IsDirectionReversedtrue Track.Thumb Thumb x:NameThumb Background{StaticResource PrimaryBrush} BorderBrush#80000000 BorderThickness1 Thumb.Style Style TargetType{x:Type Thumb} Setter PropertyFocusable Valuefalse/ Setter PropertyCursor ValueArrow/ Setter PropertyTemplate Setter.Value ControlTemplate TargetType{x:Type Thumb} Border CornerRadius3 Background{TemplateBinding Background} BorderBrush{TemplateBinding BorderBrush} BorderThickness{TemplateBinding BorderThickness}/ ControlTemplate.Triggers Trigger PropertyIsMouseOver ValueTrue Setter PropertyBackground Value{StaticResource SecondaryColorBrush}/ /Trigger Trigger PropertyIsDragging ValueTrue Setter PropertyBackground Value{StaticResource PrimaryColorBrush}/ /Trigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter /Style /Thumb.Style /Thumb /Track.Thumb /Track /Grid !-- 根据Orientation切换布局的逻辑此处略去完整代码中需处理 -- ControlTemplate.Triggers Trigger PropertyOrientation ValueHorizontal !-- 水平滚动条的布局转换 -- /Trigger /ControlTemplate.Triggers /ControlTemplate /Setter.Value /Setter /Style实操心得美化滚动条的关键在于重新定义Track和Thumb的视觉外观。我们将轨道背景设为极浅的灰色滑块Thumb使用主题色并添加圆角和悬浮效果。注意这个样式会应用到整个应用程序的所有ScrollBar上包括DataGrid内部的。为了更精细的控制你可以给DataGrid模板内的ScrollBarPART_HorizontalScrollBar和PART_VerticalScrollBar单独指定一个样式避免影响其他控件。4. 完整集成与使用实战4.1 在项目中集成自定义样式将上述所有样式代码整合到一个独立的资源字典文件如CustomDataGridStyles.xaml中。然后在你的App.xaml或特定Window/UserControl中合并这个资源字典。App.xaml中全局应用Application.Resources ResourceDictionary ResourceDictionary.MergedDictionaries ResourceDictionary SourceThemes/CustomDataGridStyles.xaml/ /ResourceDictionary.MergedDictionaries /ResourceDictionary /Application.Resources这样整个应用内的DataGrid都会默认使用这些样式如果你的样式Key是{x:Type ...}。更推荐的方式是使用x:Key然后在需要的地方显式引用。在Window或UserControl中局部应用Window.Resources ResourceDictionary ResourceDictionary.MergedDictionaries ResourceDictionary SourceCustomDataGridStyles.xaml/ /ResourceDictionary.MergedDictionaries /ResourceDictionary /Window.Resources Grid DataGrid x:NameMyDataGrid Style{StaticResource CustomDataGridStyle} ColumnHeaderStyle{StaticResource CustomColumnHeaderStyle} RowStyle{StaticResource CustomDataGridRowStyle} CellStyle{StaticResource CustomDataGridCellStyle} ItemsSource{Binding MyItemCollection} DataGrid.Columns DataGridTextColumn HeaderID Binding{Binding Id} Width80/ DataGridTextColumn Header名称 Binding{Binding Name} Width*/ DataGridTextColumn Header日期 Binding{Binding Date, StringFormatyyyy-MM-dd} Width120/ !-- 使用自定义单元格模板的列 -- DataGridTemplateColumn Header状态 Width100 DataGridTemplateColumn.CellTemplate DataTemplate Border CornerRadius3 Background{Binding StatusColor} Padding4,2 TextBlock Text{Binding StatusText} HorizontalAlignmentCenter ForegroundWhite/ /Border /DataTemplate /DataGridTemplateColumn.CellTemplate /DataGridTemplateColumn /DataGrid.Columns /DataGrid /Grid4.2 关键属性绑定与数据上下文要让样式生效DataGrid的ItemsSource必须正确绑定到数据源。在ViewModel中你需要有一个可观察的集合如ObservableCollectionT。// ViewModel 示例 public class MainViewModel : INotifyPropertyChanged { public ObservableCollectionDataItem MyItemCollection { get; } new ObservableCollectionDataItem(); public MainViewModel() { // 模拟加载数据 LoadData(); } private void LoadData() { MyItemCollection.Add(new DataItem { Id 1, Name 项目A, Date DateTime.Now, Status 正常 }); MyItemCollection.Add(new DataItem { Id 2, Name 项目B, Date DateTime.Now.AddDays(-1), Status 警告 }); // ... 更多数据 } } // 数据模型 public class DataItem { public int Id { get; set; } public string Name { get; set; } public DateTime Date { get; set; } public string Status { get; set; } // 用于模板列绑定的属性 public string StatusText Status; public Brush StatusColor { get { return Status switch { 正常 new SolidColorBrush(Colors.Green), 警告 new SolidColorBrush(Colors.Orange), 错误 new SolidColorBrush(Colors.Red), _ new SolidColorBrush(Colors.Gray) }; } } }在Window的构造函数中设置数据上下文public MainWindow() { InitializeComponent(); this.DataContext new MainViewModel(); }4.3 样式覆盖与优先级问题WPF样式遵循一个明确的优先级顺序。如果你发现自定义样式没有生效请检查以下常见问题局部样式覆盖全局样式在DataGrid上直接设置的属性如Background”Red”优先级最高会覆盖Style中的Setter。资源字典未正确合并或Key不匹配检查XAML文件路径是否正确以及Style的TargetType和x:Key是否与引用处匹配。隐式样式与显式样式如果资源字典中的样式是隐式的TargetType”{x:Type DataGrid}”且没有x:Key它会自动应用于所有该类型控件。如果同时有显式样式有x:Key被引用则显式样式优先。确保你没有在别处定义了冲突的隐式样式。一个调试技巧是在Blend或Visual Studio的设计器中右键点击DataGrid选择“编辑模板”-“编辑副本”可以查看当前生效的完整模板树帮助你定位样式被哪个环节覆盖了。5. 常见问题排查与高级技巧5.1 性能优化虚拟化与容器回收当DataGrid绑定大量数据成千上万行时默认开启的UI虚拟化VirtualizingStackPanel是保证流畅度的关键。我们的自定义样式必须确保不能破坏它。检查点在DataGrid的Style和DataGridRow的Template中确保容器如Border没有明确设置高度或包含复杂的RenderTransform这可能会阻碍虚拟化。我们之前的样式示例是安全的。启用容器回收对于超大数据集可以进一步启用容器回收以提升滚动性能。DataGrid Style{StaticResource CustomDataGridStyle} VirtualizingPanel.IsVirtualizingTrue VirtualizingPanel.VirtualizationModeRecycling ... /注意VirtualizationMode”Recycling”在大多数情况下能提升性能但如果你在行模板中使用了复杂的动画或状态可能会遇到视觉错误此时可以切换回标准的”Standard”模式。5.2 交互细节调优行双击事件DataGrid默认没有行双击事件。可以通过在DataGridRow的样式中添加事件触发器或者更推荐在ViewModel中使用交互库如Microsoft.Xaml.Behaviors.Wpf来命令绑定。!-- 在DataGridRow的Template中的Border上添加MouseDoubleClick事件处理 -- Border x:NameDGR_Border ... i:Interaction.Triggers i:EventTrigger EventNameMouseDoubleClick i:InvokeCommandAction Command{Binding DataContext.RowDoubleClickCommand, RelativeSource{RelativeSource AncestorType{x:Type DataGrid}}} CommandParameter{Binding}/ /i:EventTrigger /i:Interaction.Triggers ... /Border需要在项目中引用Microsoft.Xaml.Behaviors.WpfNuGet包。列宽调整手柄在CustomColumnHeaderStyle中我们保留了PART_LeftHeaderGripper和PART_RightHeaderGripper但它们是透明的。你可以为它们添加一个简单的样式使其在鼠标悬浮到列边缘时显示。Style TargetType{x:Type Thumb} x:KeyColumnHeaderGripperStyle Setter PropertyWidth Value8/ Setter PropertyBackground ValueTransparent/ Setter PropertyCursor ValueSizeWE/ Style.Triggers Trigger PropertyIsMouseOver ValueTrue Setter PropertyBackground Value{StaticResource PrimaryColorBrush} / /Trigger /Style.Triggers /Style然后在列头模板中为两个Thumb应用此样式Thumb ... Style”{StaticResource ColumnHeaderGripperStyle}” /。5.3 复杂单元格模板实战除了简单的DataGridTextColumnDataGridTemplateColumn提供了无限的可能性。例如在单元格内显示进度条、按钮、图片组合等。DataGridTemplateColumn Header进度 Width150 DataGridTemplateColumn.CellTemplate DataTemplate StackPanel OrientationHorizontal VerticalAlignmentCenter ProgressBar Value{Binding Progress} Width80 Height10 Margin0,0,5,0/ TextBlock Text{Binding Progress, StringFormat{}{0}%} VerticalAlignmentCenter/ /StackPanel /DataTemplate /DataGridTemplateColumn.CellTemplate /DataGridTemplateColumn DataGridTemplateColumn Header操作 WidthAuto IsReadOnlyTrue DataGridTemplateColumn.CellTemplate DataTemplate StackPanel OrientationHorizontal Button Content编辑 Command{Binding DataContext.EditCommand, RelativeSource{RelativeSource AncestorType{x:Type DataGrid}}} CommandParameter{Binding} Margin2 Padding5,2/ Button Content删除 Command{Binding DataContext.DeleteCommand, RelativeSource{RelativeSource AncestorType{x:Type DataGrid}}} CommandParameter{Binding} Margin2 Padding5,2 Background#FFDC3545 ForegroundWhite/ /StackPanel /DataTemplate /DataGridTemplateColumn.CellTemplate /DataGridTemplateColumn注意事项在模板列中使用按钮等交互控件时要特别注意事件冒泡。DataGrid本身会处理鼠标点击进行行选择按钮的点击事件可能会被父容器处理掉。确保为按钮设置了Click事件处理程序或Command绑定并且事件已正确处理e.Handled true如果需要。使用Command绑定是更符合MVVM模式的做法。5.4 样式维护与主题切换当你的应用需要支持多套主题如浅色/深色模式时将所有颜色和笔刷定义为DynamicResource而非StaticResource是关键。定义主题资源字典创建LightTheme.xaml和DarkTheme.xaml在里面用相同的Key定义不同的颜色值。在主资源字典中引用在App.xaml中根据条件切换合并的资源字典。样式中使用DynamicResource在所有样式中将Background”{StaticResource PrimaryBrush}”改为Background”{DynamicResource PrimaryBrush}”。这样当在运行时切换合并的字典时所有使用DynamicResource引用的UI元素都会自动更新。这是构建可换肤WPF应用的标准做法。我们这个DataGrid样式项目完全遵循此原则为主题切换做好了准备。
返回列表