一.前言

  申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等,若有不明白的地方可以参考本系列前面的文章,文末附有部分文章链接

本文主要内容:

  • DataGrid自定义样式;
  • ListView自定义样式;

二.DataGrid自定义样式

DataGrid是常用的数据列表显示控件,先看看实现的效果(动态图,有点大):

WPF自定义控件与样式(7)-列表控件DataGrid与ListView自定义样式

DataGrid控件样式结构包括以下几个部分:

    • 列头header样式
    • 调整列头宽度的列分割线样式
    • 行样式
    • 行头调整高度样式
    • 行头部样式
    • 单元格样式

  在本文的样式定义中,默认开启了DataGrid的虚拟化,以支持大数据,若实际使用数据确定很小,应该关闭虚拟化,因为虚拟化本身也是有成本的。样式代码:  

    <!--调整列头宽度样式-->
    <Style x:Key="DefaultColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
        <Setter Property="Width" Value="8" />
        <Setter Property="Background" Value="{StaticResource HeaderBorderBrush}" />
        <Setter Property="Cursor" Value="SizeWE" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Padding="{TemplateBinding Padding}" Background="Transparent" Margin="0 0 0 2">
                        <Rectangle HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Width="1" Fill="{TemplateBinding Background}" />
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--列头header样式-->
    <Style x:Key="DefaultDataGridColumnHeader" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="MinWidth" Value="5" />
        <Setter Property="MinHeight" Value="25" />
        <Setter Property="Height" Value="30" />
        <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
        <Setter Property="HorizontalContentAlignment" Value="Left" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Padding" Value="10,4,4,7" />
        <Setter Property="Margin" Value="0,0,0,0" />
        <Setter Property="FontWeight" Value="SemiBold"></Setter>
        <Setter Property="FontSize" Value="{StaticResource HeaderFontSize}" />
        <Setter Property="BorderThickness" Value="0,0,0,3" />
        <Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
        <Setter Property="Background" Value="{StaticResource HeaderBackground}" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="auto" />
                        </Grid.ColumnDefinitions>
                        <Border x:Name="BackgroundBorder" BorderThickness="{TemplateBinding BorderThickness}"
                                Grid.ColumnSpan="2" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" />
                        <ContentPresenter x:Name="HeaderContent"
                                          Content="{TemplateBinding Content}"
                                          ContentTemplate="{TemplateBinding ContentTemplate}"
                                          Margin="{TemplateBinding Padding}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                          RecognizesAccessKey="True"
                                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        <TextBlock x:Name="SortArrow" Style="{StaticResource FIcon}" Text="&#xe624;" Grid.Column="1" Width="20"
                                       Visibility="Collapsed" FontSize="16" Margin="1,1,3,1" />

                        <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" HorizontalContentAlignment="Left"
                               Style="{StaticResource DefaultColumnHeaderGripperStyle}" />

                        <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" HorizontalContentAlignment="Right" Background="Transparent"
                               Style="{StaticResource DefaultColumnHeaderGripperStyle}" Grid.Column="1" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <!--显示排序标示-->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True" />
                                <Condition Property="SortDirection" Value="{x:Null}" />
                                <Condition Property="CanUserSort" Value="true" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                        </MultiTrigger>
                        <!--可排序列鼠标样式-->
                        <Trigger Property="CanUserSort" Value="True">
                            <Setter Property="Cursor" Value="Hand"></Setter>
                        </Trigger>
                        <!--升序-->
                        <Trigger Property="SortDirection" Value="Ascending">
                            <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                        </Trigger>
                        <!--降序-->
                        <Trigger Property="SortDirection" Value="Descending">
                            <Setter TargetName="SortArrow" Property="Visibility" Value="Visible" />
                            <Setter TargetName="SortArrow" Property="Text" Value="&#xe625;"/>
                        </Trigger>
                        <!--第一列左边不显示分割线-->
                        <Trigger Property="DisplayIndex" Value="2">
                            <Setter Property="Visibility" Value="Collapsed" TargetName="PART_LeftHeaderGripper" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--行样式-->
    <Style x:Key="DefaultDataGridRow" TargetType="{x:Type DataGridRow}">
        <Setter Property="Foreground" Value="{StaticResource TextForeground}" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Margin" Value="0,0,0,0" />

        <Style.Triggers>
            <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                <Setter Property="Background" Value="{StaticResource ItemsAlternationContentBackground}" />
            </Trigger>
            <Trigger Property="IsSelected" Value="True">
                <Setter  Property="Background" Value="{StaticResource ItemSelectedBackground}" />
                <Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}" />
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="True" />
                    <Condition Property="Selector.IsSelectionActive" Value="True" />
                </MultiTrigger.Conditions>
                <Setter  Property="Background" Value="{StaticResource ItemSelectedBackground}" />
                <Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}" />
            </MultiTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Self}}" Value="True" />
                </MultiDataTrigger.Conditions>
                <Setter  Property="Background" Value="{StaticResource ItemMouseOverBackground}" />
                <Setter Property="Foreground" Value="{StaticResource ItemMouseOverForeground}" />
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>

    <!--行头调整高度样式 -->
    <Style x:Key="DefaultRowHeaderGripperStyle" TargetType="{x:Type Thumb}">
        <Setter Property="Height" Value="6" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Cursor" Value="SizeNS" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Thumb}">
                    <Border Padding="{TemplateBinding Padding}" Background="Transparent"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--行头部样式-->
    <Style x:Key="DefaultDataGridRowHeader" TargetType="{x:Type DataGridRowHeader}">
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="BorderThickness" Value="0,0,1,0" />
        <Setter Property="Margin" Value="0,0,0,0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridRowHeader}">
                    <Grid>
                        <Border BorderBrush="{TemplateBinding BorderBrush}"
                                Background="{TemplateBinding Background}"
                                BorderThickness="{TemplateBinding BorderThickness}"
                                Padding="{TemplateBinding Padding}"
                                Margin="{TemplateBinding Margin}"
                                SnapsToDevicePixels="True">
                            <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
                        </Border>
                        <Thumb x:Name="PART_TopHeaderGripper" VerticalContentAlignment="Top"
                               VerticalAlignment="Top" Background="Transparent" Style="{StaticResource DefaultRowHeaderGripperStyle}" />
                        <Thumb x:Name="PART_BottomHeaderGripper" VerticalContentAlignment="Bottom"
                               VerticalAlignment="Bottom" Style="{StaticResource DefaultRowHeaderGripperStyle}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--单元格样式-->
    <Style x:Key="DefaultDataGridCell"
           TargetType="{x:Type DataGridCell}">
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="BorderBrush" Value="Transparent" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="SnapsToDevicePixels" Value="True" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
                        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"
                                          Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}"
                                          Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">

                        </ContentPresenter>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property="Foreground" Value="{StaticResource ItemSelectedForeground}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <!--表格DataGrid样式-->
    <Style x:Key="DefaultDataGrid" TargetType="{x:Type DataGrid}">
        <Setter Property="MinRowHeight" Value="25" />
        <Setter Property="Background" Value="{StaticResource ItemsContentBackground}" />
        <Setter Property="BorderBrush" Value="{StaticResource ControlBorderBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="HorizontalGridLinesBrush" Value="{StaticResource GridLinesBrush}" />
        <Setter Property="VerticalGridLinesBrush" Value="{StaticResource GridLinesBrush}" />
        <Setter Property="ColumnHeaderStyle" Value="{StaticResource DefaultDataGridColumnHeader}" />
        <Setter Property="RowHeaderStyle" Value="{StaticResource DefaultDataGridRowHeader}" />
        <Setter Property="CellStyle" Value="{StaticResource DefaultDataGridCell}" />
        <Setter Property="RowStyle" Value="{StaticResource DefaultDataGridRow}" />
        <Setter Property="HeadersVisibility" Value="All" />
        <Setter Property="EnableRowVirtualization" Value="True" />
        <Setter Property="EnableColumnVirtualization" Value="False" />
        <Setter Property="AutoGenerateColumns" Value="False" />
        <Setter Property="IsReadOnly" Value="True" />
        <Setter Property="SelectionMode" Value="Single" />
        <Setter Property="SelectionUnit" Value="FullRow" />
        <Setter Property="GridLinesVisibility" Value="All" />
        <Setter Property="AlternationCount" Value="2"></Setter>
        <Setter Property="ScrollViewer.CanContentScroll" Value="True" />
        <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
        <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
        <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
        <!--列头移动列时候分割线样式-->
        <Setter Property="DropLocationIndicatorStyle">
            <Setter.Value>
                <Style TargetType="Separator">
                    <Setter Property="Background" Value="{StaticResource HeaderBorderBrush}" />
                    <Setter Property="Width" Value="2.5" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="Separator">
                                <Rectangle Fill="{TemplateBinding Background}" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" />
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>
        <!--DataGrid控件模板-->
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGrid}">
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" x:Name="border"
                            Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                        <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
                            <ScrollViewer.Template>
                                <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition x:Name="col_rowheader" Width="1" />
                                            <ColumnDefinition Width="*" />
                                            <ColumnDefinition Width="Auto" />
                                        </Grid.ColumnDefinitions>
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="Auto" />
                                            <RowDefinition Height="*" />
                                            <RowDefinition Height="Auto" />
                                        </Grid.RowDefinitions>
                                        <!--表格头部-->
                                        <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.Column="1" Grid.ColumnSpan="2"
                                                    Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
                                        <!--主数据区-->
                                        <Grid Grid.Row="1" Grid.ColumnSpan="2">
                                            <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="2" />
                                        </Grid>
                                        <!--垂直滑动条-->
                                        <ScrollBar x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}"
                                                   Orientation="Vertical" Grid.Row="0" Grid.RowSpan="3" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
                                                   Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                                                   ViewportSize="{TemplateBinding ViewportHeight}" />
                                        <!--横向滑动条-->
                                        <ScrollBar x:Name="PART_HorizontalScrollBar" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2"
                                                       Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal"
                                                       Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
                                                       Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
                                                       ViewportSize="{TemplateBinding ViewportWidth}" />
                                    </Grid>
                                </ControlTemplate>
                            </ScrollViewer.Template>
                            <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                        </ScrollViewer>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Opacity" Value="{StaticResource DisableOpacity}" TargetName="border" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsGrouping" Value="true">
                <Setter Property="ScrollViewer.CanContentScroll" Value="false" />
            </Trigger>
        </Style.Triggers>
    </Style>
View Code

相关文章: