Wpf: How to Override Part of a Controltemplate Without Redefining the Whole Style

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

You can base a Style on another Style and override specfic setters:

<Style x:Key="myStyle" TargetType="xctk:ColorPicker" BasedOn="{StaticResource {x:Type xctk:ColorPicker}}">
<!-- This will override the Background setter of the base style -->
<Setter Property="Background" Value="Red" />
</Style>

But you cannot "override" only a part of a ControlTemplate. Unfortunately you must then (re)define the entire template as a whole.

Replace part of default template in WPF

Unfortunately, I think you have to replace the entire template:

From MSDN: http://msdn.microsoft.com/en-us/library/aa970773.aspx

Controls in Windows Presentation
Foundation (WPF) have a
ControlTemplate that contains the
visual tree of that control. You can
change the structure and appearance of
a control by modifying the
ControlTemplate of that control. There
is no way to replace only part of the
visual tree of a control; to change
the visual tree of a control you must
set the Template property of the
control to its new and complete
ControlTemplate.

Style BasedOn a style defined in ControlTemplate Resources

This is not possible since you can't base a ControlTemplate on another ControlTemplate. You will have to re-define the entire template as a whole:

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

And adding a trigger to a Style won't affect or "override" the triggers that are defined in the ControlTemplate of the control so you will have to override the entire ControlTemplate from scratch.

You could of course copy the default one into your XAML markup and edit it as per your requirements.

WPF XAML Change Style Template Property for Some Elements

I would write a custom control that looks something like this:

internal class IconButton : Button
{
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}

public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(ImageSource), typeof(IconButton), new PropertyMetadata(null));

}

Then edit your style to accommodate it:

<Style TargetType="{x:Type location:IconButton}" x:Key="ButtonEllipse">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type location:IconButton}">
<StackPanel Orientation="Vertical">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0 0 0 10"/>
<Image x:Name="ButtonImage" HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="None" Source="{TemplateBinding Source"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>

Where location is a xaml-defined namespace where the IconButton class is placed.

Then just set the Source property of your button. You can mess around with the Source property to set a default as well.

How do I access an element of a parent template style in XAML?

I am having trouble accessing a named element of a parent template style in WPF.

This is not possible. You can't base a ControlTemplate on another ControlTemplate.

I am afraid you will have to re-define the entire ControlTemplate from scratch in the derived Style if you want the setter to be able find the CurrentImage element that is defined in the template of the base Style.

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

But instead of using a ControlTemplate trigger, you should be able to use a Style trigger that sets the Image property of the control itself rather than setting the Source property of the Image element in the template:

<Style x:Key="ButtonCustomStyle" TargetType="{x:Type local:ImageButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ImageButton}">
<Grid>
<Image Source="{TemplateBinding Image}" Stretch="Fill" x:Name="CurrentImage"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Image" Value="{Binding ImageHover, RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>

<Style TargetType="{x:Type local:ImageButton}"
BasedOn="{StaticResource ButtonCustomStyle}"
x:Key="Disableable">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Image" Value="\Images\disabled.png"/>
</Trigger>
</Style.Triggers>
</Style>

WPF Styles and Polymorphism

You can base a Style on Another (one only!) Style using the BasedOn property and override specific properties, but you cannot base a DataTemplate or a ControlTemplate on another template. This is not supported. A template must be defined as a whole:

WPF: Is there a way to override part of a ControlTemplate without redefining the whole style?

WPF, changing style of element inside ControlTemplate

I'm wondering if WPF offers a way to change the style of a named element defined inside a ControlTemplate, from a style declared somewhere else

Short answer: No.

You cannot access or set a property of the element (TextBlock) directly but you may set a property of the styled control (Label) that you bind to the element in the template, e.g.:

<Style x:Key="MyLabel" TargetType="Label">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock x:Name="MyTextBlock" Foreground="{TemplateBinding Foreground}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style x:Key="MyNewLabel" TargetType="Label" BasedOn="{StaticResource MyLabel}">
<Setter Property="Foreground" Value="Red" />
</Style>


Related Topics



Leave a reply



Submit