WPF - Mixing style defined in dictionary with style defined in parent control - c#

I define a custom look for Button control in a resource dictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button" x:Key="BaseButtonStyle">
<Setter Property="Background" Value="Blue"/>
</Style>
</ResourceDictionary>
Then I try to change the style of the window where the buttons are located.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml"/>
<ResourceDictionary>
<Style TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
I have what I expected in WPF designer: a blue button with red text.
But in run-time, both styles are not applied and the button has default colors.
How can I fix this?

The one below works. I just moved the Style out of the MergedDictionaries and placed it on the outer ResourceDictionary.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Button" BasedOn="{StaticResource BaseButtonStyle}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</ResourceDictionary>
</Window.Resources>
In your original XAML, I'm not sure why the designer was able to render it correctly while the WPF runtime didn't. The MSDN documentation says though that:
A merged ResourceDictionary does not have resource elements defined within it in markup. Instead, the merged dictionary is a ResourceDictionary with no markup child elements defined (or with no elements added through code), but with a URI specified for Source.
It might have something to do with it.

Related

How to change the font size in a mahapps project?

So I am trying to change the default font family and the font size in my project. I decided to start with buttons.
I do it like this (I am gonna create a separated file for my style, but now I just want to make it work somehow):
<Controls:MetroWindow.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Templates/MyTemplateSelector.xaml"/>
<ResourceDictionary Source="/Templates/FullMenu.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style BasedOn="{StaticResource MetroButton}" TargetType="Button">
<Setter Property="FontFamily" Value="Calibri" />
</Style>
</ResourceDictionary>
</Controls:MetroWindow.Resources>
and nothing changes. What is wrong?
I guess it's because program can't find "{StaticResource MetroButton}".
App.xaml
<Application x:Class="WpfApp2.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp2"
xmlns:dialogYesNo="clr-namespace:WpfApp2.DialogYesNo"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="ViewModels.xaml" />
<ResourceDictionary Source="Dialogs.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
So, you just need to use it in App.xaml after declaring metro references:
<Style TargetType="Label">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="FontFamily" Value="Segoe UI "/>
</Style>
Button uses TextBox, so button will be changed automatically.
Instead of define a style just to set fontfamily/weight you can just define in your resource directly the fontfamily and weight with a key(an example with a font that i use)
<Controls:MetroWindow.Resources>
<FontFamily x:Key="FontAwesome">/tuseradm;component/assets/fontawesome-webfont.ttf#FontAwesome</FontFamily>
</Controls:Flyout.Resources>
then in your button just set the font family
<Button FontFamily="{StaticResource FontAwesome}" Content="" />
EDIT adding another answer:
by default mahapps override the default wpf style. If you want to modify a style for let's say buttons in all your view you don't need to use based on
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="Button">
<Setter Property="FontFamily" Value="Calibri" />
<Setter Property="FontWeight" Value="ExtraLight"/>
</Style>
EDIT 2
At least for me, even if i see the change at design time using the approach exposed in the first edit, at run time the problem persist. So in my opinion, is much better to stick with my first answer. Maybe it could be annoying to set fontfamily and fontweight for each button, but it is the safest way to deal with mahapps styles. The only way to solve this 100% for sure is to find (no clue where) the template of mahapps buttons and modify it

Metro Styles in resource dictionary

I am trying to style my WPF application with Mahapps Metro. I have added the all the needed .xaml files in my MergedDictionary in the App.xaml. If I write the following in a view file,
<Button DockPanel.Dock="Left" VerticalAlignment="Top" Style="{DynamicResource SquareButtonStyle}"/>
it works, i.e., the button is styled in the SquareButtonStyle style. But if I instead add the following in my own resource dictionary,
<Style TargetType="Button">
<Setter Property="Style" Value="{DynamicResource SquareButtonStyle}"/>
</Style>
I get an error message,
Setting of the property
"System.Windows.ResourceDictionary.DeferrableContent" has caused an
exception.
(my transation of the German error message). So how can I style all buttons, e.g., with SquareButtonStyle without having to do that on each button individually?
EDIT: Here is my app.xaml (the last dictionary, ResourceDic.xaml, is my own one where the above code is):
<Application xmlns:local="clr-namespace:MGM8" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<local:MGM8_BootStrapper p7:Key="bootstrapper" xmlns:p7="http://schemas.microsoft.com/winfx/2006/xaml" />
</ResourceDictionary>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
<ResourceDictionary Source="ResourceDic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Style property can't be set inside Style of any element.
Just declare your style at root level(a root resource Dictionary or App.xmal resources). Just create the style with TargetType Button don't give any key to it. it will be applied to all the buttons in the app.
for ex:
<Style TargetType="Button" BasedOn="{StaticResource SquareButtonStyle}" >
<Setter Property="Height" Value="50"/>
<Setter Property="BorderThickness" Value="2,1" />
</Style>
So above is extending your SquareButtonStyle for your application for all buttons(only if defined at root level).
Update:
You have to use following in your own Resource Dictionary:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="SquareButtonStyle dictionary"/>
</ResourceDictionary.MergedDictionaries>
Then only you can create a button style based on SquareButtonStyle in your ResourceDictionary.

Global style isn't being applied

I have a resource dictionary file as so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TIMS.Common">
<local:ViewModelLocator x:Key="ModelLocator" />
<Style x:Key="DefaultWindowStyle" TargetType="Window">
<Setter Property="Background" Value="Cyan" />
</Style>
<Style x:Key="DefaultPageStyle" TargetType="Page">
<Setter Property="Background" Value="Red" />
</Style>
<Style x:Key="DefaultGroupBoxStyle" TargetType="GroupBox">
<Setter Property="Background" Value="DarkGray" />
</Style>
And it's included into my App.XAML as so:
<Application x:Class="TIMS.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TIMS.Common"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/TIMS;component/Resources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
However, this style doesn't apply unless I specifically set the style in the XAML for that object.
Example:
<Window x:Class="TIMS.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TIMS.Views"
xmlns:nav="clr-namespace:System.Windows.Navigation;assembly=PresentationCore"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:valueConverters="clr-namespace:TIMS.Utils.ValueConverters;assembly=TIMS.Utils"
x:Name="Main"
Title="Tote Inventory Management System - Southeastern Grocers"
Width="1024"
Style="{StaticResource DefaultWindowStyle}"
Height="768"
DataContext="{Binding MainWindowViewModel,
Source={StaticResource ModelLocator}}">
How can I make these the default style without have to explicitly set them on each element ?
If you want, for example, all your windows in your app to have the same style, remove the x:Key property of your style with TargetType Window.
Having the x:Key property will force you to explicitly use the style in your windows for it to apply. If you remove the x:key, then all the Windows of your app will use that style by default.
Here is a link that explains it with more détails : https://msdn.microsoft.com/en-us/library/ms745683(v=vs.110).aspx
In short, if you want your style to be global and apply by default to all controls of the TargetType type in your app, do not set a key to your style. If you want the style to be applied only to some of the controls of the TargetType type, set a key to your style and use it explicitly on the controls that will use it.

Using style defined in merged dictionary from another merged dictionary

Below you can see how I am trying to segregate styles by merging dictionaries (I'm skipping namespaces for the sake of cleanliness)
App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style/Colors.xaml" />
<ResourceDictionary Source="Style/HeaderStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Colors.xaml:
<SolidColorBrush x:Key="DarkTextForeground" Color="#7471b9"/>
HeaderStyle.xaml:
<Style x:Key="HeaderTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource DarkTextForeground}"/>
<Setter Property="FontWeight" Value="Black"/>
</Style>
During compilation I get a following error:
Cannot find a Resource with the Name/Key DarkTextForeground
To make It work we have to merge Colors.xaml inside HeaderStyle.xaml like this:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Colors.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="HeaderTextBlockStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource DarkTextForeground}"/>
<Setter Property="FontWeight" Value="Black"/>
</Style>
Can anyone explain to me, why I have to reference Colors.xaml in HeaderStyle.xaml? Can't I just reference styles defined in different merged dictionary?I assume that Colors.xaml is loaded before HeaderStyle.xaml so it should be visible for dictionaries defined later.
This is a response to my question from Erick Fleck at msdn forums:
In your first example each file is parsed independently and then added to the merged dictionary so they don't know anything about each other...similarly, the XAML in a merged dictionary cannot reference names in the 'parent' ResourceDictionary. In other words, you should think of a MergedDictionaries as a one-way reference.
It's the way It works I guess...

VS2012 The resource "X" could not be resolved

I have a Resources.xaml file in my project that contains a resource dictionary like so:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="GPHeaderFontSize" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="24" />
<Setter Property="Text" Value="BLAHHHHH"/>
</Style>
</ResourceDictionary>
I have included this dictionary in App.xaml like so:
<Application x:Class="GoldenPlains.App"
xmlns="schemas.microsoft.com/winfx/2006/xaml/presentation";
xmlns:x="schemas.microsoft.com/winfx/2006/xaml";
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone">
<Application.Resources>
<local:LocalizedStrings xmlns:local="clr-namespace:GoldenPlains" x:Key="LocalizedStrings"/>
<ResourceDictionary x:Key="GPResources">
<ResourceDictionary.MergedDictionaries>
<!-- Sometimes VS2012 complaining about path with blue line, please ignore it as path is correct -->
<ResourceDictionary Source="Styles/GPResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="GPRootOverlayBarStyle" TargetType="Image">
<Setter Property="Source" Value="Assets/Images/root_brown_horizontal_bar.png"/>
<Setter Property="Width" Value="729"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Stretch" Value="Uniform"/>
</style>
</Application.Resources>
...
...
</Application>
However when I try to reference an element in the resource dictionary from another Page.xaml file it cannot seem to resolve the resource....
eg:
I have tried using a binding like so:
<TextBlock Style="{Binding Path=LocalizedResources.MyTextBlockStyle, Source= {StaticResource GPResources}}"/>
it does not indicate that something is wrong but nothing shows up on the UI.
A point in the right direction would be great, cheers.
Resource Dictionary definition in the App.xaml should be about like following example :
<Application.Resources>
<ResourceDictionary>
<local:LocalizedStrings xmlns:local="clr-namespace:GoldenPlains" x:Key="LocalizedStrings"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/GPResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- Other resources if you have -->
</ResourceDictionary>
</Application.Resources>
Then, when you need to apply style defined in Resources.xaml to a UI control, simply refer to the style's key/name :
<TextBlock Style="{StaticResource GPHeaderFontSize}" />
Notes: All resources need to be inside ResourceDictionary tag, including LocalizedStrings.

Categories