Style BasedOn a style defined in ControlTemplate Resources - c#

I'm using a 3rd party ContentControl which comes with the following theme:
<Style TargetType="{x:Type xyz:XyzControl}" x:Key="XyzControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type xyz:XyzControl}">
<ControlTemplate.Resources>
<Style TargetType="Button">
<!-- A lot of styling... -->
</Style>
</ControlTemplate.Resources>
<!-- More template stuff... -->
I want to add some DataTriggers to buttons inside this control but I want to keep the default styling from the control theme.
<xyz:XyzControl>
<Button>
<Button.Style>
<Style TargetType="Button" BasedOn="{???}">
<Style.Triggers>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</xyz:XyzControl>
I tried to base on {StaticResource {x:Type Button}} but this loads the default global button style, not the default style in this context.

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.

Add a key to the 3rd party's button style :
<Style TargetType="Button" x:key="xyzbuttonStyle">
then :
<Style TargetType="Button" BasedOn="{StaticResource xyzbuttonStyle}">

Related

Why <Style TargetType="{x:Type Control}"> doesn't work? [duplicate]

I was just poking around a bit in WPF and wanted all elements on my Window to share the same margin.
I found that all Controls that are capable of having a margin derive from FrameworkElement so I tried the following:
<Window.Resources>
<Style TargetType="{x:Type FrameworkElement}">
<Setter Property="Margin" Value="10" />
</Style>
</Window.Resources>
And, this doesn't work.
I can apply this to all Buttons, but not to all Elements that derive from Button.
Am I missing something or is this simply not possible?
Am I the only one feeling like using CSS for WPF would have been a good idea?
Unfortunately, you cannot apply styles to the base FrameworkElement type; while WPF will let you write the style, it will not apply it to the controls that derive from it. It appears that this also applies to subtypes of FrameworkElement, e.g. ButtonBase, the supertype of Button/ToggleButton/RepeatButton.
You can still use inheritance, but you will have to use the explicit BasedOn syntax to apply it to the control types you want it to apply to.
<Window.Resources>
<Style TargetType="{x:Type FrameworkElement}">
<Setter Property="Margin" Value="10" />
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type FrameworkElement}}" />
</Window.Resources>
The issue is that when searching for a style WPF does not search through all classes from which the current one derives. However you can give the style a key and apply it to all elements for which you wish to have a common property. If a property is specified in the style that cannot be applied to the element you are styling, it is ignored.

WPF ControlTemplate - default style

I want to use the default style of buttons and just want to add a Grid and Stackpanel with 2-3 Bindings. When i add the ControlTemplate in my Style all Trigger-, Border-, ...settings are overwritten. How can i just add my Grid/Stackpanel/Bindings while using the rest of the default settings?
<Style x:Key="listbutton">
<Setter Property="Button.Height" Value="40"/>
<Setter Property="Button.Margin" Value="0,3"/>
<Setter Property="Button.Template">
<Setter.Value>
<ControlTemplate>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The purpose of a ControlTemplate is to define how a Control must be displayed. You can't have a ControlTemplate based on another ControlTemplate (it wouldn't make sense). What you can do is take the default ControlTemplate and modify it at your will.
The default ControlTemplate for Button can be found here

how can I design a radio button as a main design and change the main design per button

I have five radio buttons all of them have common style but different color. The styles are all separated. I would like to do a main style and to be able to change the background color for each of them separately.
Define the template in a common base style (e.g. RadioButtonBaseStyle), where you don't hard-code the background color, but use {TemplateBinding Background} instead ; then create several styles based on RadioButtonBaseStyle where you just change the Background property with a setter.
Example:
<Style x:Key="RadioButtonBaseStyle" TargetType="RadioButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton>
...
<Ellipse Fill="{TemplateBinding Background}" />
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="BlueRadioButtonStyle" TargetType="RadioButton" BasedOn="{StaticResource RadioButtonBaseStyle}">
<Setter Property="Background" Value="Blue" />
</Style>
If you need finer control, you could create additional attached properties and use them instead of the standard Background/Foreground/BorderBrush, as explained in this blog post: http://www.thomaslevesque.com/2011/10/01/wpf-creating-parameterized-styles-with-attached-properties/

Bind column header visibility without losing global style

I want to bind the column header visibility of a wpf listview to a dependency property without losing the global style (expression dark) I used.
I defined a style:
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Visibility" Value="{Binding ColumnHeaderVisibility}" />
</Style>
Then I applied it like this:
<GridView ColumnHeaderContainerStyle="{StaticResource myHeaderStyle}">
I'm using the expression dark theme. It's imported via MergedDictionaries and can be changed in runtime.
Everything is fine when the column header is invisible. But when visible it is shown in default windows style, because setting the ColumnHeaderContainerStyle overrides the expression dark style.
Using "BasedOn" on the original style is no option, because all resources are dynamic due to the requirement to change style in runtime. BasedOn only works on static resources, which won't allow changing in runtime.
What else can I do?
Not sure if this will work but you can try to base style on the default style.
<Style x:Key="myHeaderStyle" TargetType="{x:Type GridViewColumnHeader}" BasedOn="{StaticResource {x:Type GridViewColumnHeader}}">
<Setter Property="Visibility" Value="{Binding ColumnHeaderVisibility}" />
</Style>

Setting a style on Control type not working

I'm writing a very basic WPF dialog and want to apply a simple style to all objects that inherit from the Control class. The code I'm using:
<Window.Resources>
<Style TargetType="{x:Type Control}">
<Setter Property="Margin" Value="20"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Text="some text"/>
<TextBox x:Name="x_NameTextBox"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Button x:Name="x_CancelButton" Click="x_CancelButton_Click" Content="Cancel"/>
<Button x:Name="x_OkButton" Click="x_OkButton_Click" Content="OK"/>
</StackPanel>
</StackPanel>
</Window>
The Style defined above doesn't change the layout of the window at all unless I specify a key and set the style on each individual object, which is exactly what I'm trying to avoid. It also works for more specific types (setting the TargetType to Button, for example.)
Any ideas why this isn't working?
Every control when it gets instantiated it gets its Style from the explicitly defined resource or look for the immediate parent where it can get a default style. In your case the Button control will get its default Style from the platform because your App haven't defined one. Now that platform Button Style has no way to know about your custom defined Control base style. Because styles will look for a base style only when you explicitly define BasedOn
So you got only two ways
1. Define Style for every control - which you don't want I think.
2. Define Styles for the controls you are interested and set the BasedOn
<Style TargetType="{x:Type Control}">
<Setter Property="Margin" Value="20"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Control}}">
</Style>

Categories