1. 程式人生 > >WPF DataGrid自定義樣式

WPF DataGrid自定義樣式

nap nes owb 模板 設計 fault sce 做了 efi

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

WPF DataGrid自定義樣式