how to use an application resource in user control xaml - wpf

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");

Related

How do I apply styles to different `TextBlock` objects?

Here is my Application ResourceDictionary
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CABI_PO_Manager.Themes">
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="YellowTextBlock">
<Setter Property="FontSize" Value="16"/>
<Setter Property="Foreground" Value="#d8b243"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="GreenTextBlock">
<Setter Property="FontSize" Value="18"/>
<Setter Property="Foreground" Value="Green"/>
</Style>
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="RedTextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="#a01e21"/>
</Style>
</ResourceDictionary>
I want to have some default styles for a TextBlock which works
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
I found somewhere to use x:Key but I can't get it to work.
I will have several TextBlock's, How do I identify a TextBlock in the UI XAML as Red, Yellow or Green TextBlock and apply that style to them? This isn't recognized x:Key="GreenTextBlock"
<TextBlock x:Key="GreenTextBlock" Grid.Column="1" Margin="0,10,0,0" TextWrapping="Wrap" Text="PO Manager" VerticalAlignment="Top" TextAlignment="Center" FontWeight="ExtraBold"/>
If u want apply style on for example all TextBlocks in application, just use style without x:key defined e.g
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
When you are applying a style, use TargetType="{x:Type TextBlock}" instead of TargetType="TextBlock"
When do you use want to base on other style use
BasedOn="{StaticResource StyleUWantToBaseOn}"
where StyleUWantToBaseOn is style with x:Key property
And when you want to apply a specific style on lets say textblock you want to use Style property e.g:
<TextBlock Style="{StaticResource GreenTextBlock}" Grid.Column="1" />

Xaml Styles inheritance not working as expected

I am having an issue trying to make use of the BasedOn attribute of Xaml styles. I created a fairly simple style as an example.
The project consists of two main files. MainWindow.xaml and SquareButtonStyle.xaml. SquareButtonStyle makes use of the FontAwesome.WPF project to quickly get some images.
MainWindow is basically a series of buttons with an image inside it and some text.
The goal of this example is to have three different button sizes. A "medium" size, and two variants, "small" and "large", based on the medium size.
The problem is most easily seen with the large variant. The center TextAlignment, Margin and Red text color set from the Medium style, which the large is based on, is lost. It seems that instead of inheriting the style and only override the specific property I am instead inheriting the default style and overriding the property.
What am I doing wrong? It seems the only way to correct this is to not bother with BasedOn, and just make three separate styles with the full list of properties being set. Is there a way to get around this?
SquareButtonStyle.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button" x:Key="SquareButtonMediumStyle">
<Setter Property="Margin" Value="5" />
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Style.Resources>
<Style TargetType="StackPanel">
<Setter Property="Orientation" Value="Vertical" />
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="12" />
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonSmallStyle">
<Setter Property="Width" Value="55" />
<Setter Property="Height" Value="55" />
<Style.Resources>
<Style TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="10" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonLargeStyle">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Style.Resources>
<Style TargetType="StackPanel">
<Style.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
</ResourceDictionary>
MainWindow.xaml
<Window x:Class="XamlStyleExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="SquareButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<StackPanel>
<WrapPanel>
<WrapPanel.Resources>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" />
</WrapPanel.Resources>
<Button>
<StackPanel>
<TextBlock>Button 1</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 2</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 3</TextBlock>
</StackPanel>
</Button>
</WrapPanel>
<WrapPanel>
<WrapPanel.Resources>
<Style BasedOn="{StaticResource SquareButtonSmallStyle}" TargetType="Button" />
</WrapPanel.Resources>
<Button>
<StackPanel>
<TextBlock>Button 1</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 2</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 3</TextBlock>
</StackPanel>
</Button>
</WrapPanel>
<WrapPanel>
<WrapPanel.Resources>
<Style BasedOn="{StaticResource SquareButtonLargeStyle}" TargetType="Button" />
</WrapPanel.Resources>
<Button>
<StackPanel>
<TextBlock>Button 1</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 2</TextBlock>
</StackPanel>
</Button>
<Button>
<StackPanel>
<TextBlock>Button 3</TextBlock>
</StackPanel>
</Button>
</WrapPanel>
</StackPanel>
</Window>
Update
Based Upon a few answers I came up with a solution, but I don't particularly like it. It seems messy.
I now have two keyed styles. One for the StackPanel and one for the TextBlock.
MainWindow.Xaml stays the same but SquaredButtonStyle.xaml now has:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBlock" x:Key="SpecialTextBlockStyle">
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
<Style TargetType="StackPanel" x:Key="MediumNestedStackPanel">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource SpecialTextBlockStyle}" />
</Style.Resources>
</Style>
<Style TargetType="Button" x:Key="SquareButtonMediumStyle">
<Setter Property="Margin" Value="5" />
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Style.Resources>
<Style TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}">
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonSmallStyle">
<Setter Property="Width" Value="55" />
<Setter Property="Height" Value="55" />
<Style.Resources>
<!--
Implicit stack panel style in the scope of SquareButtonMediumStyle
inherits from MediumNestedStackPanel, adds stuff
-->
<Style TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource SpecialTextBlockStyle}" >
<Setter Property="FontSize" Value="10" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonLargeStyle">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Style.Resources>
<Style TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}">
<Style.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource SpecialTextBlockStyle}">
<Setter Property="FontSize" Value="14" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
</ResourceDictionary>
Those nested StackPanel styles aren't going to be involved in the BasedOn inheritance for their containing styles. If you want to do that, you'll have to set up a separate inheritance hierarchy for the nested styles:
<Style TargetType="StackPanel" x:Key="MediumNestedStackPanel">
<Setter Property="Orientation" Value="Vertical" />
<Style.Resources>
<Style TargetType="fa:ImageAwesome">
<Setter Property="Height" Value="35" />
<Setter Property="Margin" Value="5" />
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="12" />
<Setter Property="TextAlignment" Value="Center" />
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="TextWrapping" Value="Wrap" />
</Style>
</Style.Resources>
</Style>
<Style TargetType="Button" x:Key="SquareButtonMediumStyle">
<Setter Property="Margin" Value="5" />
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Style.Resources>
<!--
Implicit stack panel style in the scope of SquareButtonMediumStyle
inherits from MediumNestedStackPanel, adds nothing
-->
<Style
TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}"
/>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonSmallStyle">
<Setter Property="Width" Value="55" />
<Setter Property="Height" Value="55" />
<Style.Resources>
<!--
Implicit stack panel style in the scope of SquareButtonMediumStyle
inherits from MediumNestedStackPanel, adds stuff
-->
<Style TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}">
<Style.Resources>
<Style TargetType="fa:ImageAwesome" BasedOn="{StaticResource {x:Type fa:ImageAwesome}}">
<Setter Property="Height" Value="20" />
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="FontSize" Value="10" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonLargeStyle">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Style.Resources>
<Style TargetType="StackPanel" BasedOn="{StaticResource MediumNestedStackPanel}">
<Style.Resources>
<Style TargetType="fa:ImageAwesome" BasedOn="{StaticResource {x:Type fa:ImageAwesome}}">
<Setter Property="Height" Value="60" />
<Setter Property="Margin" Value="5" />
</Style>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="FontSize" Value="14" />
</Style>
</Style.Resources>
</Style>
</Style.Resources>
</Style>
Instead of defining an implicit TextBlock style inside the Button style(s), you should set the FontSize, Foreground, ... properties of the Button element itself:
<Style TargetType="Button" x:Key="SquareButtonMediumStyle">
<Setter Property="Margin" Value="5" />
<Setter Property="Width" Value="80" />
<Setter Property="Height" Value="80" />
<Setter Property="FontSize" Value="12" />
<Setter Property="TextBlock.TextAlignment" Value="Center" />
<Setter Property="Foreground" Value="Red"></Setter>
<Setter Property="TextBlock.TextWrapping" Value="Wrap" />
<Style.Resources>
<Style TargetType="StackPanel">
<Setter Property="Orientation" Value="Vertical" />
</Style>
</Style.Resources>
</Style>
<Style BasedOn="{StaticResource SquareButtonMediumStyle}" TargetType="Button" x:Key="SquareButtonLargeStyle">
<Setter Property="Width" Value="100" />
<Setter Property="Height" Value="100" />
<Setter Property="FontSize" Value="14" />
</Style>
Your current approach of using implicit styles for the TextBlocks won't work as you have already discovered. Please refer to the following link for more information about why:
Wpf, style is not being applied

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 share wpf style setter

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.

WPF Style with no target type?

How can I have a WPF style that has no target type ( one that can be applied to all objects) ?
<Style x:Key="Basic" TargetType="???">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FontSize" Value="12"/>
</Style>
I want to base all other styles on this "basic" style.
Regards,
MadSeb
Append "Control." to the beginning of the Property, and remove the TargetType. Then, in the styles that derive from it, use BasedOn with a StaticResource pointing at the base Style.
<Style x:Key="basicStyle">
<Setter Property="Control.FontFamily" Value="Tahoma" />
<Setter Property="Control.FontSize" Value="12" />
</Style>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource basicStyle}">
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource basicStyle}">
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource basicStyle}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,4" />
</Style>

Resources