首页 > 代码库 > WPF DataGrid自定义样式
WPF DataGrid自定义样式
微软的WPF DataGrid中有很多的属性和样式,你可以调整,以寻找合适的(如果你是一名设计师)。
下面,找到我的小抄造型的网格。它不是100%全面,但它可以让你走得很远,有一些非常有用的技巧和陷阱。
在DataGrid中的最高水平,你可以改变的外观和感觉,通过设置一些:
Property | Type | Values | Default |
AlternatingRowBackground | Brush | Any Brush | Null |
Background | Brush | Any Brush | Theme default |
ColumnHeaderHeight | Double | 0 to any positive double | NaN |
ColumnHeaderStyle | Style | Any Style | Null |
ColumnWidth | DataGridLength | 0 to any positive double, Auto, *, SizeToCells, SizeToHeader | SizeToHeader |
HeadersVisibility | DataGridHeadersVisibility | All, Row, Column, None | All |
MaxColumnWidth | Double | 0 to any positive double | Positive Infinity |
MaxRowHeight | Double | 0 to any positive double | Positive Infinity |
MinColumnWidth | Double | 0 to any positive double | 20 |
MinRowHeight | Double | 0 to any positive double | 0 |
RowBackground | Brush | Any Brush | Theme default |
RowDetailsVisibilityMode | DataGridRowDetailsVisibilityMode | Visible, VisibleWhenSelected, Collapsed | VisibleWhenSelected |
RowHeadersWidth | Double | 0 to any positive double | NaN |
RowHeight | Double | 0 to any positive double | NaN |
AlternationCount | int | 2+ | coerced to 2 |
GridLinesVisibility | DataGridGridLinesVisibility | All, Horizontal, Vertical, None | All |
HorizontalGridLinesBrush | Brush | Any Brush | Black(via metadata) |
VerticalGridLinesBrush | Brush | Any Brush | Black(via metadata) |
ItemTemplate | DataTemplate | Any DataTemplate | Null |
RowDetailsTemplate | DataTemplate | Any DataTemplate | Null |
CellStyle | Style | Any Style | Null |
ItemContainerStyle | Style | Any Style | Null |
RowHeaderStyle | Style | Any Style | Null |
RowStyle | Style | Any Style | Null |
Style | Style | Any Style | Null |
Template | ControlTemplate | ControlTemplate TargetType=Datagrid | Null |
在这里,你可以看到的一些属性(在视觉上是不是全部)的可视化表示,这将让你知道这是什么文章将涵盖。
背景:
有趣的部分是背景之间的关系:
•背景 - 将整个数据网格的背景。请注意,它可以是任何刷,固体和梯度很明显,但为什么没有一个DrawingBrush像上述(你可以看到,如果你眯着眼睛努力,不透明度=0.1)
•RowBackground和AlternatingRowBackground设置一排交替行的背景。
这些都具有较高的Z顺序比DataGrid的背景,当然,这意味着你可以得到视觉组合物W/网格的背景。
请注意,,默认颜色RowBackground主题(默认值是不透明的); DataGrid的背景将是不可见的,除非你重写这些行的背景是部分透明。
•AlternationCount是将用于行的样式或颜色的总数。这个数字是一个指标为基础(,意义开始计数为1,而不是0)。 ?如果你设置AlternationCount的> 2,您的行从第三排AlternationCount的将被指定为默认的背景刷值(主题)。
?的方式来设置不同的背景或样式的每一行的基础上AlternationCount是压倒一切的样式DataGridRow触发的基础上AlternationIndex,这实际上是零指数。
?,如果设置AlternatingRowBackground刷,将被分配到行,其中(rownumber%AlternationIdex)== 1
压倒一切的的RowStyle调整背景下基于AlternationIndex下面是一个例子:
<Style x:Key="DataGridDemoRowStyle" TargetType="{x:Type Custom:DataGridRow}"><Style.Triggers><Trigger Property="AlternationIndex" Value="http://www.mamicode.com/2" >
<Setter Property="Background" Value="http://www.mamicode.com/{StaticResource RowBackgroundAlternationIndex2Brush}" /></Trigger><Trigger Property="AlternationIndex" Value="http://www.mamicode.com/3"><Setter Property="Background" Value="http://www.mamicode.com/{StaticResource RowBackgroundAlternationIndex3Brush}" /></Trigger></Style.Triggers></Style>
请注意,有目的的,我只覆盖AlternationIndex= 2,3。对于AlternationIndex= 0时,它使用RowBackground。
对于AlternationIndex= 1,它使用从DataGrid中AlternatingRowBackground的。
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type Custom:DataGridColumnHeader}" >
<Setter Property="Background" Value="http://www.mamicode.com/#88800080" />
<Setter Property="Foreground" Value="http://www.mamicode.com/White" />
<Style.Triggers> <Trigger Property="SortDirection" Value="http://www.mamicode.com/{x:Null}">
<Setter Property="Background" Value="http://www.mamicode.com/{DynamicResource DataGridHeaderBackgroundBrush}" /> <Setter Property="BorderBrush" Value="http://www.mamicode.com/Transparent" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="http://www.mamicode.com/True" /> <Condition Property="SortDirection" Value="http://www.mamicode.com/{x:Null}" />
</MultiTrigger.Conditions> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
<Setter Property="BorderBrush" Value="http://www.mamicode.com/{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="http://www.mamicode.com/true" /> <Condition Property="SortDirection" Value="http://www.mamicode.com/{x:Null}" />
</MultiTrigger.Conditions> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
<Setter Property="BorderBrush" Value="http://www.mamicode.com/{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <Trigger Property="SortDirection" Value="http://www.mamicode.com/Ascending"> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource DataGridHeaderSortedBackgroundBrush}" />
</Trigger> <Trigger Property="SortDirection" Value="http://www.mamicode.com/Descending"> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource DataGridHeaderSortedBackgroundBrush}" />
</Trigger> </Style.Triggers></Style>
DataGrid列头
我通常自定义标题上一个数据网格,来完成两个任务:
•TWEAK的背景的标头,包括触发器悬停,选择等
•调整控制模板的头,主要是因为默认的样式显示排序是顶部ColumnHeader中,我喜欢它的侧面。
我的直觉是,自定义标题的背景将是一个简单的样式覆盖。这是我的尝试:
如果您运行的示例代码对这种风格,你会发现,排序的DataGrid中显示的默认样式消失的方向箭头“的原因,因为这是,DataGridColumnHeader使用DataGridHeaderBorder在其模板; DataGridHeaderBorder是一种智能边境检查,如果你设置了背景,如果你做了,它就像一个边界,如果你没有设定一个背景,它的行为巧妙,并呈现三角形指标排序的代码。
如果你想排序方向箭头,和不同的背景,你应该覆盖的模板,并使用常规的边界,什么都想要的背景。覆盖的模板是不是太辛苦了,这里是一个例子:
<Style x:Key="DatagridColumnHeaderCustomTemplateStyle"
TargetType="{x:Type Custom:DataGridColumnHeader}"><Setter Property="SnapsToDevicePixels" Value="http://www.mamicode.com/True" /><Setter Property="MinWidth" Value="http://www.mamicode.com/0" /><Setter Property="MinHeight" Value="http://www.mamicode.com/28" />
<Setter Property="Foreground" Value="http://www.mamicode.com/White" /><Setter Property="Cursor" Value="http://www.mamicode.com/Hand" /><Setter Property="Template"> <Setter.Value><ControlTemplate TargetType="{x:Type Custom:DataGridColumnHeader}">
<Grid><Grid.ColumnDefinitions><ColumnDefinition Width="*" /><ColumnDefinition Width="Auto" /></Grid.ColumnDefinitions><Border x:Name="BackgroundBorder" BorderThickness="0,1,0,1" Background="{StaticResource DataGridHeaderSortedBackgroundBrush}" BorderBrush="{StaticResource DataGridHeaderSortedBorderBrush}" Grid.ColumnSpan="2" />
<ContentPresenter Margin="6,3,6,3" VerticalAlignment="Center" /><Path x:Name="SortArrow" Visibility="Collapsed" Data="http://www.mamicode.com/M0,0 L1,0 0.5,1 z" Stretch="Fill" Grid.Column="1" Width="8" Height="6" Fill="White" Margin="0,0,8,0" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.4" /><Rectangle Width="1" Fill="#AAC377" HorizontalAlignment="Right" Grid.ColumnSpan="2" /><Rectangle Width="1" Margin="0,0,1,0" Fill="#425B10" HorizontalAlignment="Right" Grid.ColumnSpan="2" /><Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/><Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/></Grid><ControlTemplate.Triggers>
<Trigger Property="SortDirection" Value="http://www.mamicode.com/{x:Null}"><Setter TargetName="BackgroundBorder" Property="Background" Value="http://www.mamicode.com/{DynamicResource DataGridHeaderBackgroundBrush}" /><Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="http://www.mamicode.com/Transparent" /></Trigger><MultiTrigger><MultiTrigger.Conditions><Condition Property="IsMouseOver" Value="http://www.mamicode.com/True" /><Condition Property="SortDirection" Value="http://www.mamicode.com/{x:Null}" /></MultiTrigger.Conditions><Setter Property="Background" TargetName="BackgroundBorder" Value="http://www.mamicode.com/{StaticResource DataGridHeaderMouseOverBackgroundBrush}" /><Setter Property="BorderBrush" TargetName="BackgroundBorder" Value="http://www.mamicode.com/{StaticResource DataGridHeaderBorderBrush}" /></MultiTrigger><MultiTrigger><MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="http://www.mamicode.com/true" /><Condition Property="SortDirection" Value="http://www.mamicode.com/{x:Null}" /></MultiTrigger.Conditions><Setter TargetName="BackgroundBorder" Property="Background" Value="http://www.mamicode.com/{StaticResource DataGridHeaderMouseOverBackgroundBrush}" /><Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="http://www.mamicode.com/{StaticResource DataGridHeaderBorderBrush}" /></MultiTrigger><Trigger Property="SortDirection" Value="http://www.mamicode.com/Ascending"><Setter TargetName="SortArrow" Property="Visibility" Value="http://www.mamicode.com/Visible" /><Setter TargetName="SortArrow" Property="RenderTransform"><Setter.Value><RotateTransform Angle="180" /></Setter.Value></Setter></Trigger><Trigger Property="SortDirection" Value="http://www.mamicode.com/Descending"><Setter TargetName="SortArrow" Property="Visibility" Value="http://www.mamicode.com/Visible" /></Trigger><Trigger Property="DisplayIndex" Value="http://www.mamicode.com/0"><Setter Property="Visibility" Value="http://www.mamicode.com/Collapsed" TargetName="PART_LeftHeaderGripper"></Setter></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
注意上面有几件事情:我取代DataGridHeaderBorder正常的边界,我增加了一个小的“三角”排序方向,并把它转换(或翻转)的基础上SortDirection。
DataGrid行头
对我来说,这是最常见的“调整”RowHeader。 调整的宽度(默认是太小) •调整的背景,以配合我的主题。 •实施行选择点击的行头,此功能不出来的方块。 •错误处理发生在RowHeader 我的第一个尝试的API时,是通过样式设置行头的宽度。后来,我认识到DataGrid中暴露的RowHeaderWidth的直接,所以我现在用的,而不是。这是一个简单的属性setter。 对于调整的背景下,我第一次尝试在DataGrid中设定一个的RowHeader的样式属性。基本的风格,我想是这样的:
<Style x:Key="DataGridRowHeaderBackgroundStyle" TargetType="{x:Type Custom:DataGridRowHeader}">
<Setter Property="Background" Value="http://www.mamicode.com/Gray" />
</Style>
它的工作原理,但类似的ColumnHeaders我失去了功能。在运行时,它看起来像这样:
正如你会发现,它失去了分隔每一行的的行DataGridLines,有没有徘徊,等等。
然后我就开始覆盖模板。的变化,实际上是微不足道的,我注意到DataGridHeaderBorder默认回到它的基类(境)的渲染,这主要是隐含设定一个BorderThickness就可以了假网格的行分隔符,和具有约束力的颜色DataGrid的HorizontalGridLinesBrush..
这里是,我创建的DataGridRowHeader,模板.. (和下面的解释上的一些额外的陷阱)。
<Stylex:Key="{x:TypeCustom:DataGridRowHeader}"TargetType="{x:TypeCustom:DataGridRowHeader}"> <SetterProperty="Background"Value="http://www.mamicode.com/{StaticResource RowHeaderBackgroundBrush}" /> <SetterProperty="Template"> <Setter.Value> <ControlTemplate TargetType="{x:TypeCustom:DataGridRowHeader}"> <Grid> <Custom:DataGridHeaderBorder IsSelected="{TemplateBinding IsRowSelected}" IsHovered ="{TemplateBinding IsMouseOver}" IsPressed="{TemplateBinding IsPressed}" BorderBrush="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGrid}}, Path=HorizontalGridLinesBrush}" Background="{TemplateBinding Background}" BorderThickness="0,1,0,0" Padding ="{TemplateBinding Padding}" Orientation="Horizontal" SeparatorVisibility="{TemplateBinding SeparatorVisibility}" SeparatorBrush="{TemplateBinding SeparatorBrush}" Margin="0,-1,0,0"> <StackPanel Orientation="Horizontal"> <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/> <Control SnapsToDevicePixels="false" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}}, Path=(Validation.HasError), Converter={StaticResource bool2VisibilityConverter}}" Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}}, Path=ValidationErrorTemplate}" /> </StackPanel> </Custom:DataGridHeaderBorder> <Thumb x:Name="PART_TopHeaderGripper" VerticalAlignment="Top" Height="3" Style="{StaticResource RowHeaderGripperStyle}"/> <Thumb x:Name="PART_BottomHeaderGripper" VerticalAlignment="Bottom" Height="3" Style="{StaticResource RowHeaderGripperStyle}"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="http://www.mamicode.com/True"> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource RowHeaderIsMouseOverBrush}" /> </Trigger> <Trigger Property="IsRowSelected" Value="http://www.mamicode.com/True"> <Setter Property="Background" Value="http://www.mamicode.com/{StaticResource RowBackgroundSelectedBrush}" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
有趣的变化是:
•我不得不使用一个隐式的风格。虽然DataGrid中确实有有RowHeaderStyle财产,一些没有工作对我来说,这是奇怪的,因为的RowHeaderStyle工作正常,当我用的风格,没有覆盖的模板。
•被设置为0,1,0,0的BorderThickness DataGridHeaderBorder.. ,这使得它的网格线绘制相当于中,我offseted的保证金为0,-1,0,0,以确保这与DataGridRow网格线对齐。
•在DataGridHeaderBorder BorderBrush时,势必到DataGrid的HorizontalGridLinesBrush。
•我继续绑定到本地刷在字典中的IsRowSelected,增加了一个触发器。所以,现在的RowHeader会显示选中状态的可视化。
•我添加了一个触发器IsMouseOver,它仅仅是预期的行为“。
•我设置了拇指的夹持器用于调整行高度尺寸3。我之所以这样做,是因为我喜欢可以双击头,选择整个行;在DataGrid中实现此功能,但大拇指都这么大了,他们得到的方式,试图点击在的RowHeader。大小为2或3的大拇指,似乎做精拖留下了足够的空间,为,点击RowHeader选择行。
另一个有趣的功能,我玩RowHeader时了解到的是,如果你双击调整行拇指,它会返回到原来的大小。尼斯触摸(我不知道)。
•
的报告的RowHeader错误的任务,我没有调整的DataGridRowHeader,在所有相关的错误做任何的事情。我做的所有通过DataGrid的ErrorTemplate属性,指向ErrorTemplate2在我的资源字典。
<ControlTemplate x:Key="ErrorTemplate2">
<Grid MinWidth="20" MinHeight="20">
<Rectangle Fill="{StaticResource ErrorTemplateBrush}" />
</Grid>
</ControlTemplate>
<digression>
我不喜欢ErrorTemplate是一个ControlTemplate。在我看来,它应该是一个DataTemplate访问DatagridRow的背景和在DatagridRow的错误收集。作为一个“解决方法,你可以尝试通过控制自己的调整RowHeaderTemplate到这一点,并传递到控制,作为占位符ErrorTemplate的,这样的DataContext:
<Control SnapsToDevicePixels="false"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}},
Path=(Validation.HasError),
Converter={StaticResource bool2VisibilityConverter}}"
Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}},
Path=ValidationErrorTemplate}"
DataContext="{Binding
RelativeSource={RelativeSource AncestorType={x:Type Custom:DataGridRow}},
Path=(Validation.Errors)[0].ErrorContent }"
>
然后,您可以调整的ErrorTemplate的DataGrid的一个工具提示:
<ControlTemplate x:Key="ErrorTemplate2">
<Grid MinWidth="20" MinHeight="20" ToolTip="{Binding}">
<Rectangle Fill="{StaticResource ErrorTemplateBrush}" >
</Rectangle>
</Grid>
</ControlTemplate>
和得到的东西更有帮助的错误消息,如下所示:
单元格样式
默认情况下,DataGrid的细胞时选择一个主题,蓝色背景(见下面的关闭想法),我不喜欢这样,所以我用DataGrid的CellStyle照顾。覆盖默认的模板,并删除选择的触发器:
<Style x:Key="DataGridCellStyle" TargetType="{x:Type Custom:DataGridCell}"><Setter Property="Background" Value="http://www.mamicode.com/Transparent" /><Setter Property="BorderBrush" Value="http://www.mamicode.com/Transparent" /><Setter Property="BorderThickness" Value="http://www.mamicode.com/1" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="{x:Type Custom:DataGridCell}">
<Border Background="Transparent" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="0" SnapsToDevicePixels="True"><ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/></Border></ControlTemplate></Setter.Value></Setter></Style>
RowDetailsTemplate RowDetails模板时,会显示一排。它是与上下文的行的DataTemplate。在本演示中,实现很简单,我所做的就是把一个TextBlock,但你可以做更复杂的RowDetails,一个真正的项目。 <DataTemplate x:Key="RowDetailsTemplate">
<Grid TextBlock.Foreground="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Text="RowDetails Go here" Grid.Row="0"/>
<TextBlock Text="{Binding }" Grid.Row="1"/>
</Grid>
</DataTemplate>
主要的原因提RowDetailsTemplate是强调的“同步”,需要做的选择一行时,RowDetailsTemplate,RowBackground,和RowHeader的背景都应该调整,以确保其背景颜色协调。在这种情况下,如果你看上面的模板,我并确保他们相匹配的选择,将背景设置为“深蓝色”梯度。
“WPF设计器友好”标记的调整,我们就从一个普通的网格(见左图)出写一行代码样式的网格(见右图)。
WPF DataGrid自定义样式