关于C#:在WPF中覆盖样式值的正确方法

Proper way to override style values in WPF

我想在WPF中编辑DataGrid的单元格样式。因此,使用Expression Blend,我可以直接转到-"对象和时间线">>"数据网格">>"编辑其他模板">>"编辑单元格样式">>"编辑副本"
这是页面上显示的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<SolidColorBrush x:Key="{x:Static DataGrid.FocusBorderBrushKey}" Color="#FF000000"/>
<Style x:Key="DataGridCellStyle1" TargetType="{x:Type 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 DataGridCell}">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
        </Trigger>
        <Trigger Property="IsKeyboardFocusWithin" Value="True">
            <Setter Property="BorderBrush" Value="{DynamicResource {x:Static DataGrid.FocusBorderBrushKey}}"/>
        </Trigger>
    </Style.Triggers>
</Style>

但是我只想更改填充和背景。相反,它给了我25行代码,包括单元模板!我是否错过了某些东西,是否有一种更好的样式化样式,而当我只想更改两个项目时,不必携带太多不必要的代码呢?


签出样式的" BasedOn "属性...

例如,以下样式从DataGridColumnHeader中获取所有内容,并且仅覆盖Horizo??ntalContentAlignment属性:

1
2
3
4
<Style x:Key="CenterAlignedColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}"
       BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>


在WPF中覆盖控件模板要求您完全替换模板。您可能只想更改模板的一个方面,但是其结果是Expression转储了其余模板的副本,以便可以覆盖它。确保您以正确的方式覆盖了单元(我不确定还有另一种方式)。一些控件(想到了ListView)可以让您换出数据模板而不会覆盖整个控件模板,但是我不确定这是您想要的,还是可以用DataGrid完成。

查看答案:在WPF中替换默认模板的一部分


要执行您想做的事情,通常只需设置背景和填充属性的样式即可:

1
2
3
4
<Style TargetType="DataGridCell">
    <Setter Property="Padding" Value="10" />
    <Setter Property="Background" Value="Green" />
</Style>

但是,在这种情况下,DataGridCell的默认控件模板似乎忽略了填充值,因此您将需要用一个没有实现的填充替换它。以下内容基于您发布的默认模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<Style TargetType="DataGridCell">
    <Setter Property="Padding" Value="10" />
    <Setter Property="Background" Value="Green" />
    <Setter Property="Template">
    <Setter.Value>
        <ControlTemplate TargetType="{x:Type DataGridCell}">
            <Border BorderBrush="{TemplateBinding BorderBrush}"
                    BorderThickness="{TemplateBinding BorderThickness}"
                    Background="{TemplateBinding Background}"
                    SnapsToDevicePixels="True">
                <ContentPresenter
                    Margin="{TemplateBinding Padding}" <!-- this bit does the padding -->
                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
            </Border>
        </ControlTemplate>
    </Setter.Value>
    </Setter>
</Style>