Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to override style values in WPF

Tags:

c#

wpf

xaml

I want to edit a the cell style of a DataGrid in WPF. So using Expression Blend I right go to - Objects and Timeline>>DataGrid>>Edit Additional Templates>>Edit CellStyle>>Edit a Copy
Here's what what appears on the page:

<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>

But I only want to change the padding and background. Instead it has given me 25 lines of code, including the cell template! Am I missing something, is there a better way of styling items like this without having to bring so much extra unnecessary code when I only want to change two items?

like image 542
Jim_CS Avatar asked Dec 21 '11 18:12

Jim_CS


People also ask

How to override style in wpf?

Overriding control templates in WPF requires you to completely replace the template. You may have wanted to change just the one aspect of the template but the result of that is Expression dumping a copy of the rest of the template so that it can be overridden.

How do I extend a style in WPF?

You can also extend a style that has an x:Key by using the x:Key of the style. For example, if there was a style named Header1 and you wanted to extend that style, you would use BasedOn="{StaticResource Header1}" .


3 Answers

Check out the "BasedOn" attribute for Styles...

For example the following style takes everything from DataGridColumnHeader and only overrides the HorizontalContentAlignment property:

<Style x:Key="CenterAlignedColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}" 
       BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
like image 56
KornMuffin Avatar answered Sep 19 '22 23:09

KornMuffin


Overriding control templates in WPF requires you to completely replace the template. You may have wanted to change just the one aspect of the template but the result of that is Expression dumping a copy of the rest of the template so that it can be overridden. Make sure you're overriding the cell in the proper way (I'm not sure there's another way). Some controls (ListView comes to mind) will let you swap out data templates without overriding the entire control template, but I'm not sure that's what you want, or if it can be done with DataGrid.

See the answer to this: Replace part of default template in WPF

like image 26
digitlworld Avatar answered Sep 18 '22 23:09

digitlworld


To do what you want to do, you would usually just set the background and Padding properties in a style:

<Style TargetType="DataGridCell">
    <Setter Property="Padding" Value="10" />
    <Setter Property="Background" Value="Green" />
</Style>

However in this case it seems that the default control template for DataGridCell ignores the padding value, so you will need to replace it with an implementation that doesn't. The following is based on the default template that you posted:

<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>
like image 39
saus Avatar answered Sep 19 '22 23:09

saus