How to share wpf style setter - wpf

I have the following ResourceDictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="StyleComboBox" TargetType="{x:Type ComboBox}">
<Setter Property="BorderBrush" Value="DarkGray" />
<Setter Property="BorderThickness" Value="1" />
<!-- Styles for ComboBox -->
</Style>
<Style x:Key="StyleTextBox" TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="DarkGray" />
<Setter Property="BorderThickness" Value="1" />
<!-- Styles for Textbox -->
</Style>
</ResourceDictionary>
How is it possible to use only at one position the setter?

Styles in wpf can be inherited from another style.
<Style x:Key="baseStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="12" />
<Setter Property="Background" Value="Orange" />
</Style>
<Style x:Key="boldStyle" BasedOn="{StaticResource baseStyle}" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold" />
</Style>
source
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="baseStyle" TargetType="Control">
<Setter Property="BorderBrush" Value="DarkGray" />
<Setter Property="BorderThickness" Value="1" />
</Style>
<Style x:Key="StyleComboBox" BasedOn="{StaticResource baseStyle}" TargetType="{x:Type ComboBox}">
<!-- Styles for ComboBox -->
</Style>
<Style x:Key="StyleTextBox" BasedOn="{StaticResource baseStyle}" TargetType="{x:Type TextBox}">
<!-- Styles for Textbox -->
</Style>
</ResourceDictionary>

<Style TargetType="Control" x:Key="Controlbase">
<Setter Property="Control.BorderThickness" Value="10"/>
</Style>
<Style x:Key="StyleComboBox" TargetType="{x:Type ComboBox}" BasedOn="{StaticResource Controlbase}">
<Setter Property="BorderBrush" Value="DarkGray" />
<!-- Styles for ComboBox -->
</Style>
<Style x:Key="StyleTextBox" TargetType="{x:Type TextBox}" BasedOn="{StaticResource Controlbase}">
<Setter Property="BorderBrush" Value="DarkGray" />
<!-- Styles for Textbox -->
</Style>
I hope this will help.

Curious if this worked for you. Need to be careful in that you're redefining the style of say a ComboBox as based on your Control base style. Presumably the control template is not affected by this as that would be bad. IOW A ComboBox is much more than just a simple control and needs to inherit the styles and preserve the control template of all that it means to be a ComboBox. IE Its a SelectorControl that inherits from an ItemsControl etc.
I wonder if rebasing its style would also cause it to prefer/use the default control template of a Control rather than retaining its "identity" as say a ComboBox.

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 I override/replace a property of a child-item in a default style

The default wpf MenuItem (on Menu) is constructed out of controls approx. like this:
grid; outer-rectangle; bg-rectangle; inner-rectangle; dockpanel; popup.
The dockpanel in turn consists of:
contentpresenter[icon]; path; contentpresenter[text]
The contentpresenter[text] consists of a TextBlock control.
What I want to achieve is to define a Style, as simple as possible, to change the VerticalAlignment property of this TextBlock, but only for the TextBlock in MenuItem, not in general.
<Style x:Key ="TextBlockCenterStyle" TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="MenuItem">
<Setter Property="FontSize" Value="11" />
<Setter Property="ItemContainerStyle" Value="TextBlockCenterStyle" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>
I tried Style.Resources and ItemContainerStyle.
Cannot get it to work. ItemContainerStyle throws TargetInvocationException (from NullReferenceException) at run-time.
When it is possible it should be a general solution, something like FindChildControl?!
Did you try ItemContainerStyle?
Something like:
<MenuItem ItemContainerStyle = {StaticResource MyItemContainerStyle}../>
Then the MyItemContainerStyle have your
<Style x:Key ="MyItemContainerStyle" TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
=============== answer after EDIT ======================
try this:
<Style TargetType="MenuItem">
<Setter Property="FontSize" Value="11" />
<Setter Property="ItemContainerStyle" Value="{StaticResource TextBlockCenterStyle}" />
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Style.Resources>
</Style>

how to use an application resource in user control xaml

I have a app.xml with some resources in it such as:
<Application.Resources>
<con:EnumToVisibilityConverter x:Key="EnumToVisibilityConverter" />
<con:NegateBoolConverter x:Key="NegateBoolConverter" />
<Style TargetType="FrameworkElement" x:Key="BaseStyle">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Margin" Value="3"/>
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="25" />
</Style>
<Style TargetType="CheckBox" BasedOn="{StaticResource BaseStyle}">
</Style>
<Style TargetType="DatePicker" BasedOn="{StaticResource BaseStyle}">
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource BaseStyle}">
</Style>
<Style TargetType="Label" BasedOn="{StaticResource BaseStyle}">
</Style>
<Style TargetType="Button" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Width" Value="75" />
<Setter Property="Height" Value="23" />
<Setter Property="Margin" Value="5,2,2,5" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Top" />
</Style>
</Application.Resources>
I want to use them in my user control xaml as follow:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="App.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Since my user control xaml is in View directory, the above mentione syntax is not accepted by system and complained that it can not find view/app.xaml. How can I add path to the Source so it can find it?
You don't need to do that. Application resources are available all over the app, so all you need to do is either this in xaml:
Style="{StaticResource BaseStyle}"
Or this in C# (inside your control's code):
Style baseStyle = (Style)this.FindResource("BaseStyle");

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

WPF Change fontSize of button with style fails?

Well i have my file Styles.xaml thats merged in the Application.xaml so it applies to every thing..
here are my styles
<Style TargetType="{x:Type Control}" x:Key="baseStyle">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style TargetType="Button" BasedOn="{StaticResource baseStyle}">
<Setter Property="Margin" Value="2,0,2,0"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="FontSize" Value="50"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="FontSize" Value="12"/>
</Style>
When im in the editor this seems to work but when i run the application the font-size of the buttons are shrinked to their normal sizes..
My guess is that the buttons create a TextBlock when their content is set to a string and then use the textblock style.. but how can i override this?
You're right about
My guess is that the buttons create a
TextBlock when their content is set to
a string and then use the textblock
style
. See this post.
A workaround is to define a
DataTemplate for System.String, where
we can explicitly use a default
TextBlock to display the content. You
can place that DataTemplate in the
same dictionary you define the
TextBlock style so that this
DataTemplate will be applied to
whatever ContentPresenter effected by
your style.
So adding the DataTemplate at the end to Styles.xaml will fix the problem
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style TargetType="{x:Type Control}" x:Key="baseStyle">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="FontSize" Value="12"/>
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource baseStyle}">
<Setter Property="Margin" Value="2,0,2,0"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="Foreground" Value="Red" />
<Setter Property="FontSize" Value="50"/>
</Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontFamily" Value="Verdana"/>
<Setter Property="Foreground" Value="Green" />
<Setter Property="FontSize" Value="24"/>
</Style>
<DataTemplate DataType="{x:Type sys:String}">
<TextBlock Text="{Binding}">
<TextBlock.Resources>
<Style TargetType="{x:Type TextBlock}"/>
</TextBlock.Resources>
</TextBlock>
</DataTemplate>
</ResourceDictionary>
This will keep your Style for a TextBlock but the TextBlock created in a Button for example won't be effected by it
I tried your styles, and it works well. So your styles are not the problem. I think it's the place you merged the style as you wrote. You'd better put your ResourceDictionary Styles.xaml in your MainWindow file instead of your Application.xaml.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<StackPanel>
<TextBlock>TTT</TextBlock>
<Button>BBB</Button>
</StackPanel>
</Window>
But your problem remains unclear, if it's not the solution could you clarify a bit more the way you use your styles by posting this part of your code?

Resources