锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / WPF / WPF用Style和Template定制DataGrid
服务方向
人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品原创,禁止全文或局部转载,禁止任何形式的非法使用,侵权必究。点名“简易百科”和闲暇巴盗用锐英源原创内容。

WPF用Style和Template定制DataGrid


前几天写DataGrid,想实现DataGrid不同行不同背景色,在codeproject上找到了个好文章翻译给大家,自己也提高下。要点是滚动条也可以定制,这比Winform写代码定制要灵活强大,希望大家能够喜欢。本文核心特点是脚本定制,这和WinForm的代码定制方式不同, 更灵活,同时非法操作也更少,是进步。但关联因素比较多。

提示下:看不懂codeproject,找锐英源。

介绍 

在本文中,我们将介绍如何更改数据网格控件的外观。

如何自定义DataGrid的DataGridColumnHeader、DataGridRow、DataGridCell、DatagridRowHeader和ScrollViewer的模板。

在这篇文章中你可以学习,如何使用 DatagridRowHeader 样式扩展多个 RowDetailTemplate, 

如何更改 DataGrid 中的 ScrollBar 样式。  

背景

DataGrid 是 WPF 中一个强大的控件。它用于在自定义网格中呈现数据集合。

 

使用代码

DataGridColumnHeader 样式  

默认列标题: 

 

 自定义列标题: 

 

第 1 步:创建 TargetType=DatagridColumnHeader 的样式

C++
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Height" Value="35" />
<Setter Property="SeparatorBrush" Value="DarkRed" />
<Setter Property="FontWeight" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<!-- Your Template goes here -->
</Setter.Value>
</Setter>
</Style>

 

 第 2 步:创建 TargetType=DatagridColumnHeader 的 ControlTemplate 并在模板中添加。 

C++
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<Border x:Name="columnHeaderBorder"
BorderThickness="1"
Padding="3,0,3,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#A5A5A5" />
<GradientStop Offset="1" Color="#4B4B4B" />
</LinearGradientBrush>
</Border.BorderBrush>
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#DEB40A" />
<GradientStop Offset="1" Color="#FF7F00" />
</LinearGradientBrush>
</Border.Background>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</Grid>
</ControlTemplate>

 使用 LinearGradientBrush 设置背景颜色来创建边框,以使用指定的偏移量设置线性的多种颜色。

LinearGradientBrush 有 2 个属性

- StartPoint:用于在给定点(X 和 Y)填充颜色。

- EndPoint:渐变颜色将停止填充到给定的端点(X 和 Y)

 ContentPresenter 保存 DataGridColumn 的内容(数据/标题文本等)。

 

第 3 步:为鼠标悬停时更改 DataGridColumn 的 BackgroundColor 目标而添加 VisualState。  

C++
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="columnHeaderBorder"
Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0" Value="LightYellow" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

VisualStateManager 用于在特定状态发生变化时进行动画控制(Normal、MouseOver、Focus 等) 

Storyboard 是一个容器时间线,为其子动画提供对象和属性定位信息。简而言之,所有动画都放在情节提要中。

Storyboard 具有 Storyboard.TargetNameStoryboard.TargetProperty附加属性。这些属性用于将指定的动画设置为目标控件的目标属性。

ColorAnimationUsingKeyFrames用于在指定的 Duration 内沿一组 KeyFrame 为 Color 属性的值设置动画。 

在上面的代码中,添加了 ColorAnimationUsingKeyFrames 以将数据网格columnHeaderBorder控件的GardientStop[1] 颜色从 #FF7F00 更改 LightYellow。 

要了解有关动画和故事板的更多信息,请阅读链接帖子。

当用户将鼠标悬停在数据网格列上时,在 Storyboard 中添加了 ColorAnimation 以更改颜色。

DataGridRow 样式  

默认行: 

 

自定义行: 



如上图2所示,第一个是默认的DataGrid样式,

第二个是使用行颜色、备用行颜色和鼠标悬停行颜色自定义样式。 

第 1 步:创建 TargetType=DataGridRow 的样式

C++
<Style TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="LightYellow" />
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<!-- Row Template goes here -->
</Setter.Value>
</Setter>
</Style>

 在上面的代码中,为 DataGridRow 创建了样式并将行背景属性设置为LightYellow。

步骤 2:为 DataGridRow 创建模板

C++
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#AAFFFFAA" />
<GradientStop Offset="1" Color="#AAFFD455" />
</LinearGradientBrush>
</Border.Background>
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<DataGridDetailsPresenter Grid.Row="1"
Grid.Column="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="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.Row},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>

 在上面的代码中,DataGridRow ControlTemplate 包含 DataGridCellPresenter、DataGridDetailsPresenter 和 DataGridRowHeader。

保持所有这些 Presenter 原样。

我们只需要更改主边框背景颜色,

边框 ( DGR_Border )  背景颜色设置为 LinerGradientBrush 并结合黄色和弧度。

所以每一行在网格中都用这个背景颜色突出显示。

 

第 3 步:现在,添加 VisualState 以设置交替行、鼠标悬停行和选定行的 DataGridRow 背景颜色。 

要设置交替行颜色,首先我们需要在 DataGrid 中将 AlternationCount 属性值设置为 2。 

C++
<DataGrid Name="dataGrid1"     AlternationCount="2"   />

然后,添加 VisualStates(AlternatingRow、MouseOver 和 Selected Row) 

C++
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Normal_AlternatingRow">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#AAF0C570" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border"
Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[1].(GradientStop.Color)">
<EasingColorKeyFrame KeyTime="0" Value="#AAFF7F00" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal_Selected">
<Storyboard>
<!-- ColorAnimation here same as Normal_AlternatingRow state -->
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<!-- ColorAnimation here same as Normal_AlternatingRow state -->
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

 要更改备用行颜色,visualstatemanager 为数据网格行提供 Normal_AlternatingRow  视觉状态。

在上面的代码片段中,添加了三个 VisualState

一个用于 AlternateRow,一个用于 MouseOverRow,一个用于 SelectedRow。 

所有都有 ColorAnimation,它会在特定状态更改时更改  DGR_Border控件背景的 GradientStop[0] 和 GradientStop[1] 颜色。 

DataGridCell 样式  

我创建了这种样式来隐藏默认的数据网格行选择颜色(蓝色)。 

因为即使设置 DataGridRow 选择的颜色,它也不会影响 UI,DataGridCell 默认样式会将背景颜色覆盖为其默认颜色。       

C++
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border x:Name="border"
Background="Transparent"
BorderBrush="Transparent"
BorderThickness="1"
SnapsToDevicePixels="True">

<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

在上面的代码中,我在边框控件中将子控件设置为 ConentPresenter,并将边框控件放置在 ControlTemplate 根目录中。

我将边框控件背景和边框笔刷设置为透明, 因此隐藏了 DatGridCell 背景。

现在,选定的行样式将从 DataGridRow Selected VisualSate 应用。  

DataGrid 行详细信息模板

 

第 1 步:为 RowDetails 创建 DataTemplate 

C++
<DataTemplate x:Key="RowDetailTemplate">
<Grid x:Name="RowDetailGrid"
Width="470"
Height="Auto"
Margin="5">
<Border HorizontalAlignment="Left"
VerticalAlignment="Top"
CornerRadius="5">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="WhiteSmoke" />
<GradientStop Offset="0.75" Color="#AAFFFFAA" />
<GradientStop Offset="1" Color="#AAFFD455" />
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Margin="10"
HorizontalAlignment="Center"
FontSize="18"
FontWeight="Black"
Text="Temperature Description" />
<TextBlock Grid.Row="1"
Margin="10"
HorizontalAlignment="Left"
Text="{Binding Description}"
TextWrapping="WrapWithOverflow" />
</Grid>
</Border>
<Border Margin="0 0 8 0" CornerRadius="5">
<Border.Background>
<RadialGradientBrush Center="0.5,1" GradientOrigin="0,1"
Opacity="0.3" RadiusX="0.8" RadiusY="0.8">
<GradientStop Offset="1" Color="#AAFFD455" />
<GradientStop Offset="1" Color="WhiteSmoke" />
</RadialGradientBrush>
</Border.Background>
</Border>
</Grid>
</DataTemplate>

在上面的代码中,两个边框控件放置在网格内。

在 First Border Backgroud 中使用 LinearGradientBrush 设置,数据绑定以在 RowDetails 面板中显示。

在 Second Birder 中,背景设置为 RadialGradientBrush,以在细节面板顶部放置一个光环,如上图所示( RowDetail 面板中的温度描述文本周围的颜色)。 

下图将描述 RadialGradient 的工作原理(填充颜色)。 

 

  

第 2 步:为 Show/Hide RowDetail 面板创建 ToggleButton 样式。

C++
< Style TargetType= " ToggleButton" 

使用路径创建了两个形状,一个用于折叠行详细信息面板,一个用于展开行详细信息面板。 

    

Path 用于创建三角形、六边形、椭圆等形状或图形对象,Path 继承自 Shape 类。

您还可以使用路径绘制图片。您可以使用 Fill 属性用颜色填充形状。




第 3 步:为选中/未选中状态的更改路径添加 VisualState。

C++
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="DefaultPath"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Duration="0"
Storyboard.TargetName="CheckedPath"
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="CheckedPath"
Storyboard.TargetProperty="(Path.Fill).(SolidColorBrush.Color)">
<SplineColorKeyFrame KeyTime="0:0:0.2" Value="#CCAA0000" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

 

ObjectAnimationUsingKeyFrames动画允许您为动画关键帧使用对象而不是原始值

ObjectAnimationUsingKeyFrames 动画中唯一允许的 DiscreteObjectkeyframes 关键帧。

在上面的代码中,Expand/Collapsed Path 的 Visiblity 使用在Checked VisualState之上的 ObjectAnimationUsingKeyFrames 进行了更改。

在 ToggleButton 扩展路径的选中状态下,使用 ColorAnimationUsingKeyFrames 更改了颜色。

SplineColorKeyFrame用于使用样条插值将前一个关键帧的颜色值设置为它自己的值。它在由 KeySpline 属性确定的值之间创建变量转换。

第 4 步:在 DataGrid 中设置 RowDetailTemplate,在 RowHeaderTemplate 中添加 ToggleButton。 

C++
<DataGrid Name="dataGrid1"		         
Margin="10"
HorizontalAlignment="Left"
VerticalAlignment="Top"
AlternationCount="2"
MinRowHeight="26"
RowDetailsTemplate="{StaticResource RowDetailTemplate}" >
<DataGrid.RowHeaderTemplate>
<DataTemplate>
<ToggleButton x:Name="RowHeaderToggleButton"
Click="ToggleButton_Click"
Cursor="Hand" />
</DataTemplate>
</DataGrid.RowHeaderTemplate>
</DataGrid>

 我已将 RowDetailTemplate 设置为StaticResource,因为 DataTemplate 是在同一页面中创建的。如果 DataTemplate 或 Style 放置在 ResourceDictionary 中,那么您必须使用DynamicResource设置 Style 。

要在每行表头添加ToggleButton,需要设置RowHeaderTemplate,如上源码所示,ToggleButton控件设置在DataGrid RowHeaderTemplate的DataTemplate中。

它将在每个行标题上显示三角形图像(使用路径创建),例如:

 现在,我们需要在单击 Triangle 时展开 RowDetail,或者我们可以说选中 TogggleButton

第 5 步:处理 ToggleButton 单击事件以展开/折叠 RowDetail

首先,您必须在 DataGrid 样式中设置一个属性,以更改所选 DataGridRow 上的 RowDetail Visibility

 

C++
< Style TargetType= “ {x:Type DataGrid}” >        < Setter Property= “ RowDetailsVisibilityMode” Value= “ VisibleWhenSelected” / >  

当特殊的DataRow选择上时,会设置RowDetailVisibilityMode到Visible。


C++
private void ToggleButton_Click(object sender, RoutedEventArgs e)
{
DependencyObject obj = (DependencyObject)e.OriginalSource;
while (!(obj is DataGridRow) && obj != null) obj = VisualTreeHelper.GetParent(obj);
if (obj is DataGridRow)
{
if ((obj as DataGridRow).DetailsVisibility == Visibility.Visible)
{
(obj as DataGridRow).IsSelected = false;
}
else
{
(obj as DataGridRow).IsSelected = true;
}
}
}

 在 ToggleButton 单击事件中,首先使用VisualTreeHelper.GerParent方法找到所选切换按钮的当前数据网格行。

VisualTreeHelper 用于执行涉及可视树中节点的任务。

GetParent 方法将返回一个表示可视对象父级的DependencyObject值。

现在,根据 ToggleButton 选中状态和 DataGridRow.DetailsVisibility设置 DataGridRow IsSelected属性。

 

 第 6 步:添加事件处理程序 - RowDetailsVisibilityChanged 以管理 ToggleButton 选中状态 


 

C++
<DataGrid Name="dataGrid1"		          	RowDetailsVisibilityChanged="dataGrid1_RowDetailsVisibilityChanged">     
 

 - 在 .CS 文件中创建方法,该方法将从父 DependencyObject 中按名称查找 FrameworkElement。

C++
public static FrameworkElement GetTemplateChildByName(DependencyObject parent, string name)
{
int childnum = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childnum; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is FrameworkElement && ((FrameworkElement)child).Name == name)
{
return child as FrameworkElement;
}
else
{
var s = GetTemplateChildByName(child, name);
if (s != null)
return s;
}
}
return null;
}

上述方法将遍历 Parent DependencyObject 中所有可用的子控件,并按其名称返回子控件。此方法是递归方法,它将调用方法本身,直到找到子控件或直到最后一个子元素,无论是第一个。

如果未找到子元素,它将迭代到最后一个子元素并返回值。 

VisualTreeHelper.GetChild 方法将在 Visual Tree 中找到第一个孩子。  

 - 创建 DataGrid RowDetailsVisibilityChanged 事件处理程序  

C++
private void dataGrid1_RowDetailsVisibilityChanged(object sender,DataGridRowDetailsEventArgs e)
{
DataGridRow row = e.Row as DataGridRow;
FrameworkElement tb = GetTemplateChildByName(row, "RowHeaderToggleButton");
if (tb != null)
{
if (row.DetailsVisibility == System.Windows.Visibility.Visible)
{
(tb as ToggleButton).IsChecked = true;
}
else
{
(tb as ToggleButton).IsChecked = false;
}
}

}

 上述方法将从 Selected DataGridRow 模板中找到 ToggleButton。

如果找到了 ToggleButton,且DataGridRow DetailsVisibility=Visible则将其IsChecked属性设置为true

否则将IsChecked  属性设置为false。

基于行详细信息可见性更改,此方法用于更改 Expand/Collapsed Path(Shape) 

 

DataGrid 滚动条样式

 

  

第 1 步:创建重复按钮样式 

C++
<Style x:Key="ScrollButtons" TargetType="{x:Type RepeatButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Name="Border" Background="Transparent">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>  

 更改重复按钮模板以删除默认样式。

在 ControlTemplate 中添加了边框控件并将背景设置为透明。现在将ContentPresenter 放在 Border 内,

ContentPresenter 用于显示 ContentControl 的内容。

当您要自定义控件模板时,请不要忘记将 ContentPresenter 放在 Template 中,否则您的数据将不会显示。 

 第 2 步:创建所需的画笔和颜色资源 

C++
<Color x:Key="BackgroundColor">#AE2F33</Color>
<Color x:Key="StandardColor">#800000</Color>
<Color x:Key="HoverColor">#AAC64D45</Color>
<Color x:Key="PressedColor">#AA0000</Color>
<Color x:Key="DialogBackgroundColor">#FF666666</Color>
<Color x:Key="ScollBarBackgroundStart">#77C64D45</Color>
<Color x:Key="ScollBarBackgroundEnd">#99C64D45</Color>
<SolidColorBrush x:Key="StandardBrush" Color="{StaticResource StandardColor}" />
<SolidColorBrush x:Key="HoverBrush" Color="{StaticResource HoverColor}" />
<SolidColorBrush x:Key="BackgroundBrush" Color="{StaticResource BackgroundColor}" />
<LinearGradientBrush x:Key="ScollBarBackgroundBrush" StartPoint="0,0" EndPoint="1,0">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="{StaticResource ScollBarBackgroundStart}" />
<GradientStop Offset="1" Color="{StaticResource ScollBarBackgroundEnd}" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>  

WPF 提供以下不同类型的画笔: 

- SolidColorBrush:将用纯色绘制区域。 

-LinearGradientBrush:将绘制具有线性渐变的区域。 

- RadialGradientBrush:将绘制具有径向渐变的区域。焦点定义渐变的起点,圆定义渐变的终点。 

- ImageBrush:将用图像绘制区域。 

- DrawingBrush:使用 System.Windows.Media.Drawing 绘制区域,其中可以包括形状、文本、视频、图像或其他绘图。 

画笔用于用图形/颜色填充/绘制对象/FrameworkElements。

我为滚动条的默认、悬停和按下状态创建了画笔。 

 

第 3 步:创建 ScrollBar Thumb 样式    

C++
<Style x:Key="ScrollThumbs" TargetType="{x:Type Thumb}">
<Setter Property="Background" Value="{StaticResource BackgroundBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Grid Name="Grid">
<Rectangle Name="Rectangle1"
Width="7"
Height="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Fill="{TemplateBinding Background}"
RadiusX="4"
RadiusY="4" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

 创建的 TargetType=Thumb 样式,通过将 Style 设置为 StaticResource/DynamiceResource,它将在滚动条中应用 Thumb 样式。 

在 ControlTemplate 中添加了 Rectangle 控件并将 Fill 属性设置为  {TemplateBinding Background}  ,此 TemplateBinding 将从控件背景绑定颜色,因此它将 Rectangle 填充颜色设置为  BackgroundBrush   ( <Setter Property="Background" Value="{StaticResource BackgroundBrush}" / >) 

 

第 4 步:创建 ScrollBar 样式 

C++
<Style x:Key="MyScrollBar" TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="{DynamicResource ScollBarBackgroundBrush}" />
<Setter Property="Width" Value="12" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ScrollBar}">
<Grid x:Name="GridRoot"
Width="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidth}}"
Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="18" />
<RowDefinition Height="0.00001*" />
<RowDefinition MaxHeight="18" />
</Grid.RowDefinitions>
<RepeatButton x:Name="DecreaseRepeat"
Command="ScrollBar.LineUpCommand"
Foreground="{StaticResource StandardBrush}"
Style="{DynamicResource ScrollButtons}">
<Path x:Name="DecreaseArrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="F1 M 3.5,0L 0,7L 7,7L 3.5,0 Z "
Fill="{StaticResource StandardBrush}" />
</RepeatButton>
<Track x:Name="PART_Track"
Grid.Row="1"
Focusable="false"
IsDirectionReversed="true">
<Track.Thumb>
<Thumb x:Name="Thumb"
Background="{DynamicResource ButtonDefaultBrush}"
Style="{DynamicResource ScrollThumbs}" />
</Track.Thumb>
</Track>
<RepeatButton x:Name="IncreaseRepeat"
Grid.Row="2"
Command="ScrollBar.LineDownCommand"
Foreground="{DynamicResource StandardBrush}"
Style="{DynamicResource ScrollButtons}">
<Path x:Name="IncreaseArrow"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="F1 M 3.5,7L 7,0L 0,0L 3.5,7 Z "
Fill="{StaticResource StandardBrush}" />
</RepeatButton>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

在 ScollBar ControlTemplate 中,添加了两个重复按钮(一个用于顶部,一个用于底部)和 Thumb。

对于 Top RepeatButton,您必须将 Command 设置为  ScrollBar.LineUpCommand 并设置之前在 ResourceDictionary 中创建的 Style={DynamicResource ScrollButtons}。

使用路径为顶部按钮创建形状并放置在重复按钮中。 

 同样,对于底部重复按钮,您必须将 Command 设置为  ScrollBar.LineDownCommand  设置与顶部按钮相同的样式。

创建 Track 并将 Thumb 添加到Track.Thumb。将以前创建的 Thumb 样式设置为 Track.Thumb。 

Track 表示一个控制基元,用于处理 System.Windows.Controls.Primitives 的定位和大小。用于设置 Primitives.Track.Value 的拇指控件 

 

第 5 步:为 RepeatButton 和 Thumb 添加触发器以更改 MouseOver 上的颜色并更改 Pressed 属性。 

C++
<ControlTemplate.Triggers>
<Trigger SourceName="IncreaseRepeat" Property="IsMouseOver" Value="true">
<Setter TargetName="IncreaseArrow" Property="Fill"
Value="{StaticResource HoverBrush}" />
</Trigger>
<Trigger SourceName="Thumb" Property="IsMouseOver" Value="true">
<Setter TargetName="Thumb" Property="Background"
Value="{StaticResource HoverBrush}" />
</Trigger>
<Trigger SourceName="Thumb" Property="IsDragging" Value="true">
<Setter TargetName="Thumb" Property="Background"
Value="{StaticResource StandardBrush}" />
</Trigger>
</ControlTemplate.Triggers> <span style="font-size: 9pt;"> </span> > 

在上面的示例中,我为 RepeatButton 创建了 MouseOver 触发器来更改 Fill 属性。

为 Thumb 2 创建触发器,一个用于 MouseOver,一个用于 Dragging 以更改 Thumb Background 属性。 

您也可以在其他属性上创建触发器(例如:按下、启用等)

第 6 步:最后,在 DataGrid Tempalate 中设置 ScrollBar 样式。 

C++
<ControlTemplate TargetType="{x:Type DataGrid}">
<ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<!--your DataGridColumnHeadersPresenter,ScrollContentPresenter --> <ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
Grid.Row="1"
Grid.ColumnSpan="2"
CanContentScroll="{TemplateBinding CanContentScroll}" />
<ScrollBar x:Name="PART_VerticalScrollBar"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
Style="{DynamicResource MyScrollBar}"
ViewportSize="{TemplateBinding ViewportHeight}" />
<ScrollBar x:Name="PART_HorizontalScrollBar" Maximum="{TemplateBinding ScrollableWidth}"
Orientation="Horizontal"
ViewportSize="{TemplateBinding ViewportWidth}" />
</ControlTemplate>
<ScrollViewer.Template>
<ItemPresenter />
</ScrollViewer>
</ControlTemplate >  
 

在 DataGrid ControlTemplate 的 ScrollViewer 中添加了两个 ScrollBar。

一种用于垂直滚动,一种用于水平滚动。将 Style 设置为  {DynamicResource MyScrollBar}  ,就像之前创建的滚动条样式一样。

在这篇文章中,我尝试包含完全自定义 DataGrid 样式的所有要点,以更改控件的外观和外观。 

兴趣点

在开发过程中,请记住如何在需要时显示多个 RowDetails 面板和显示/隐藏 RowDetail 面板。

为此,我有 Crated ToggleButton 并添加到 DataGrid 的 RowHeaderTemplate 中,单击 ToggleButton 显示 RowDetails 并再次单击隐藏详细信息面板。 

 我也在这篇文章中实现了与显示/隐藏行详细信息面板相关的更改。这是 DataGrid 中的新事物。 

 

友情链接
版权所有 Copyright(c)2004-2021 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州大学北校区院(文化路97号院)内