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="2" >
<Setter Property="Background" Value="{StaticResource RowBackgroundAlternationIndex2Brush}" /> </Trigger> <Trigger Property="AlternationIndex" Value="3"> <Setter Property="Background" Value="{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="#88800080" />
<Setter Property="Foreground" Value="White" />
<Style.Triggers> <Trigger Property="SortDirection" Value="{x:Null}">
<Setter Property="Background" Value="{DynamicResource DataGridHeaderBackgroundBrush}" /> <Setter Property="BorderBrush" Value="Transparent" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True" /> <Condition Property="SortDirection" Value="{x:Null}" />
</MultiTrigger.Conditions> <Setter Property="Background" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="true" /> <Condition Property="SortDirection" Value="{x:Null}" />
</MultiTrigger.Conditions> <Setter Property="Background" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <Trigger Property="SortDirection" Value="Ascending"> <Setter Property="Background" Value="{StaticResource DataGridHeaderSortedBackgroundBrush}" />
</Trigger> <Trigger Property="SortDirection" Value="Descending"> <Setter Property="Background" Value="{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="True" /> <Setter Property="MinWidth" Value="0" /> <Setter Property="MinHeight" Value="28" />
<Setter Property="Foreground" Value="White" /> <Setter Property="Cursor" Value="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="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="{x:Null}"> <Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource DataGridHeaderBackgroundBrush}" /> <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="Transparent" /> </Trigger> <MultiTrigger> <MultiTrigger.Conditions> <Condition Property="IsMouseOver" Value="True" /> <Condition Property="SortDirection" Value="{x:Null}" /> </MultiTrigger.Conditions> <Setter Property="Background" TargetName="BackgroundBorder" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" /> <Setter Property="BorderBrush" TargetName="BackgroundBorder" Value="{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <MultiTrigger> <MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="true" /> <Condition Property="SortDirection" Value="{x:Null}" /> </MultiTrigger.Conditions> <Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource DataGridHeaderMouseOverBackgroundBrush}" /> <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource DataGridHeaderBorderBrush}" /> </MultiTrigger> <Trigger Property="SortDirection" Value="Ascending"> <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" /> <Setter TargetName="SortArrow" Property="RenderTransform"> <Setter.Value> <RotateTransform Angle="180" /> </Setter.Value> </Setter> </Trigger> <Trigger Property="SortDirection" Value="Descending"> <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" /> </Trigger> <Trigger Property="DisplayIndex" Value="0"> <Setter Property="Visibility" Value="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="Gray" />
</Style>
它的工作原理,但類似的ColumnHeaders我失去了功能。在運行時,它看起來像這樣:
正如你會發現,它失去了分隔每一行的的行DataGridLines,有沒有徘徊,等等。
然后我就開始覆蓋模板。的變化,實際上是微不足道的,我注意到DataGridHeaderBorder默認回到它的基類(境)的渲染,這主要是隱含設定一個BorderThickness就可以了假網格的行分隔符,和具有約束力的顏色DataGrid的HorizontalGridLinesBrush..
這里是,我創建的DataGridRowHeader,模板.. (和下面的解釋上的一些額外的陷阱)。
<Stylex:Key="{x:TypeCustom:DataGridRowHeader}"TargetType="{x:TypeCustom:DataGridRowHeader}"> <SetterProperty="Background"Value="{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="True"> <Setter Property="Background" Value="{StaticResource RowHeaderIsMouseOverBrush}" /> </Trigger> <Trigger Property="IsRowSelected" Value="True"> <Setter Property="Background" Value="{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="Transparent" /> <Setter Property="BorderBrush" Value="Transparent" /> <Setter Property="BorderThickness" Value="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設計器友好”標記的調整,我們就從一個普通的網格(見左圖)出寫一行代碼樣式的網格(見右圖)。
轉自:http://blog.csdn.net/metal1/article/details/41291537