"inherit" style of theme in wpf - wpf

I'm using one of the themes in CodePlex and I want to add some modifications on the style but not to change their code. How can I inherit the theme style?

<Style x:Key="Style1">
<Setter Property="Control.Background" Value="Yellow"/>
</Style>
<Style x:Key="Style2" BasedOn="{StaticResource Style1}">
<Setter Property="Control.Foreground" Value="Blue"/>
</Style>
MSDN reference: http://msdn.microsoft.com/en-us/library/system.windows.style.basedon.aspx
Another example (basing a style on a style with no explicit key):
<Style x:Key="Style3" BasedOn="{StaticResource {x:Type ComboBox}}">
<Setter Property="Control.Foreground" Value="Blue"/>
</Style>
Just load the extending resource dictionary after the base resource dictionary via XAML or code.

Related

Wpf - Create a Style in a resource dictionary that sets properties of children of a grid [duplicate]

Is it possible to define a ResourceDictionary in a Style?
For example, suppose I wanted to have two different Styles for StackPanels and in one I want all the buttons to be blue and the other I want them to be red. Is this possible?
Something like
<Style x:Key="RedButtonsPanel" TargetType="{x:Type StackPanel}">
<Setter Property="Orientation" Value="Horizontal" />
<Setter Property="StackPanel.Resources">
<Setter.Value>
<ResourceDictionary>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
</Setter.Value>
</Setter>
</Style>
The above code fails with an error about the Property value of a Setter cannot be null (even though it's obviously not null).
I can do something like
<ResourceDictionary x:Key="RedButtons">
<Style TargetType="{x:Type Button}">
<Setter Property="Width" Value="100" />
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
<StackPanel Resources={StaticResource RedButtons} />
However I was wondering if there was a way to merge the ResourceDictionary into the style.
Try adding the Style(s) for each TargetType to the DockPanel Style.Resources.
I did something similar with a DockPanel Style. Wanted all Buttons or Separators added to the DockPanel to get styled in a consistent manner.
Here's a sample:
<Style x:Key="DockPanelToolBarStyle" TargetType="{x:Type DockPanel}">
<Style.Resources>
<Style TargetType="Button" BasedOn="{StaticResource ButtonToolBarStyle}" />
<Style TargetType="Separator" BasedOn="{StaticResource SeparatorToolBarStyle}" />
</Style.Resources>
<Setter Property="Height" Value="45"/>
<Setter Property="Background" Value="{StaticResource ToolBarBrush}"/>
</Style>
StackPanel.Resources is not a DependencyProperty and therefore I don't believe you will be able to set that property within the style.

Can't set style with TargetType Shape

I am trying to set the Shape.Stroke property for several shape types using a style in WPF.
<Style.Resources>
<Style TargetType="{x:Type Polyline}">
<Setter Property="Stroke" Value="White"/>
</Style>
<Style TargetType="{x:Type Path}">
<Setter Property="Stroke" Value="White"/>
</Style>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Stroke" Value="White"/>
</Style>
...
</Style.Resources>
It does not seem possible to just set the style for the base class Shape.
<Style.Resources>
<Style TargetType="{x:Type Shape}">
<Setter Property="Stroke" Value="White"/>
</Style>
</Style.Resources>
Is there no better way than the first option I listed?
When WPF searches for an implicit Style, it looks for a resource whose key matches the DefaultStyleKey of the element to be styled. The convention in WPF is that every control T overrides the DefaultStyleKey to be typeof(T). WPF will not attempt to fall back to the base type's style key if a match is not found.
Ellipse, for example, has an implied[1] default style key of typeof(Ellipse), so WPF will only attempt to resolve an implicit style with that key; a resource keyed on typeof(Shape) will not be applied.
If you want to use implicit styles, you will need to define an implicit Style per concrete type. However, those styles may inherit setters and triggers from a common base Style:
<Style x:Key="x" TargetType="{x:Type Shape}">
<Setter Property="Stroke" Value="Black"/>
</Style>
<Style TargetType="Ellipse" BasedOn="{StaticResource x}" />
<Style TargetType="Path" BasedOn="{StaticResource x}" />
<Style TargetType="Polyline" BasedOn="{StaticResource x}" />
Note that while implicit styles for base types will not be applied automatically, they are still compatible, and they can be applied explicitly:
<Style x:Key="StrokedShape" TargetType="{x:Type Shape}">
<Setter Property="Stroke" Value="Black"/>
</Style>
<!-- ... -->
<Ellipse Style="{StaticResource StrokedShape}" />
[1] Some WPF elements do not override DefaultStyleKey. Shape and its subclasses are among them. In such cases, WPF assumes the default convention.

inherit style from default style

In my project there is a custom style for text box. It is defined as:
<Style TargetType="TextBox"/>
So it is applied to all text box child controls by default.
I need to create another style that is based on default style. But how do I specify in the BasedOn attribute that my new style should use the default style?
Use the type of the control you would like to extend
BasedOn="{StaticResource {x:Type TextBox}}"
Full example:
<Style x:Key="NamedStyle" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter property="Opacity" value="0.5" />
</Style>
#Aphelion has the correct answer. I would like to add that the order in which items are defined in the ResourceDictionary matter.
If you override the default style of a slider and you want to base another slider style on that, you must declare the "based on" slider after the override style.
For example, if you do this:
<Style x:Key="BlueSlider" TargetType="{x:Type Slider}" BasedOn="{StaticResource {x:Type Slider}}">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="{x:Type Slider}">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
BlueSlider will have a blue background with the default (white) foreground.
But if you do this:
<Style TargetType="{x:Type Slider}">
<Setter Property="Foreground" Value="Yellow"/>
</Style>
<Style x:Key="BlueSlider" TargetType="{x:Type Slider}" BasedOn="{StaticResource {x:Type Slider}}">
<Setter Property="Background" Value="Blue"/>
</Style>
BlueSlider will have a blue background and a yellow foreground.

Removing Selected State of all templates (Global Style)

I need to remove the selected state (effect) or whatever it is called from every control in my interface. You know the black dashed line...
What are the ways for it to be done?
P.S. Is it normal for a fully customized XAML page to use 30MB RAM?
Thanks in advance.
That is controls by the FocusVisualStyle of the associated control. Unfortunately, you cannot disable that globally for all controls using a single Style or setting. Instead, you'd have to individually turn it off for every control type.
For example, you can include the following styles in your Application.Resources to turn it off for the specified controls:
<Style TargetType="Button">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
<Style TargetType="RepeatButton">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
<Style TargetType="ToggleButton">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
<Style TargetType="TreeViewItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
<!-- ETC -->
But keep in mind, that if you use the Style property on any of the controls or if you have any other implicit styles defined then those will prevent the styles above from being applied.
Or as Rachel point out, you could do this:
<Style x:Key="FrameworkElementStyleKey" TargetType="FrameworkElement">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
<Style TargetType="Button" BasedOn="{StaticResource FrameworkElementStyleKey}" />
<Style TargetType="RepeatButton" BasedOn="{StaticResource FrameworkElementStyleKey}" />
<Style TargetType="ToggleButton" BasedOn="{StaticResource FrameworkElementStyleKey}" />
<Style TargetType="TreeViewItem" BasedOn="{StaticResource FrameworkElementStyleKey}" />
<!-- ETC -->
Functionally, both approaches above have the same effect.

How to base a style on another style in a resource dictionary?

I have a theme that is applied to all buttons in a resource dictionary. Now I want to add a trigger to the button while inheriting the style changes from the dictionary. I tried the following code, but it says that the control cannot be found. How can I fix it ?
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
<conv:ErrorContentConverter x:Key="ErrorContentConverter" />
<Style x:Key="ValidTrigger"
TargetType="Control" BasedOn="{StaticResource {x:Type Control}}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsValid}" Value="False">
<Setter Property="IsEnabled" Value="false" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
The base template:
<Style TargetType="{x:Type Button}" BasedOn="{x:Null}">
<Setter Property="FocusVisualStyle"
Value="{DynamicResource NuclearButtonFocusVisual}" />
<Setter Property="Foreground" Value="#FF042271" />
<Setter Property="FontFamily" Value="Trebuchet MS" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Padding" Value="3" />
<Setter Property="Template" Value="{DynamicResource ButtonTemplate}" />
</Style>
One trick I've used in the past: in your ResourceDictionary that defines blanket styles for your application, add an x:Key to the style you'd like to inherit from, like so:
<Style TargetType="{x:Type Button}" x:Key="ButtonStyle">
<!-- your style here -->
</Style>
To apply this style to all controls of the specified type (Button in this example) without having to explicitly set the Style attribute of every Button, add another style that's BasedOn this style, but doesn't have a key:
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonStyle}" />
Using this method, all Buttons in your application will automatically inherit your custom style, but you can still create additional styles BasedOn the ButtonStyle entry and avoid blowing away all of your custom styling.
Give your base Style a name, say FooStyle.
In the example you gave, modify the TargetType and BasedOn to look as follows:
<Style x:Key="ValidTrigger"
TargetType="{x:Type Control}" BasedOn="{StaticResource {x:Type Control}}" >
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsValid}" Value="False">
<Setter Property="IsEnabled" Value="false" />
</DataTrigger>
</Style.Triggers>
</Style>
I think there is no base style defined for "control" so your
BasedOn="{StaticResource {x:Type Control}}" part won't find anything.
You probably want to change
<Style x:Key="ValidTrigger" TargetType="Control" BasedOn="{StaticResource {x:Type Control}}" >
to
<Style x:Key="ValidTrigger" TargetType="Button" BasedOn="{StaticResource {x:Type Button}}" >

Resources