Global style isn't being applied - c#

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.

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

Setting the style of a WPF UserControl

I know I can set the style of a UserControl like so in the control by adding an attribute:
Style="{StaticResource MyStyle}"
And having a style in my ResourceDictionary that looks something like the following:
<Style x:Key="MyStyle" TargetType="{x:Type UserControl}">
<Style.Resources>
<Style TargetType="Label">
<!-- Label Setters -->
</Style>
<Style TargetType="TextBox">
<!-- TextBox Setters -->
</Style>
</Style.Resources>
</Style>
But is there a way I can set the style of the UserControl in the ResourceDictionary directly like:
<Style x:Key="MyStyle" TargetType="{x:Type MyControl}">
Essentially my question is, can I apply the style directly to the control instead of to the controls components?
EDIT:
What I am trying to accomplish is something like the following:
<Style x:Key="MyStyle" TargetType="{x:Type MyControl}">
<Setter Property="Background" Value="Black"/>
</Style>
<Style x:Key="{x:Type MyControl}" TargetType="{x:Type MyControl}" BasedOn="{StaticResource MyStyle}"/>
Where the second line applies the style to all controls in the application, if you do something similar with a normal control this approach works.
However this only sets the Background of the UserControl, so how can I apply that same background to its components.
How can I do it with the UserControl?
You can directly set the UserControl's Style like this:
<UserControl x:Class="MyNamespace.MyControl" xmlns:local="MyNamespace" ...>
<UserControl.Style>
<Style>
<Setter Property="local:MyControl.MyProperty" Value="..."/>
...
</Style>
</UserControl.Style>
</UserControl>
or like this:
<UserControl x:Class="MyNamespace.MyControl" xmlns:local="MyNamespace" ...>
<UserControl.Style>
<Style TargetType="local:MyControl">
<Setter Property="MyProperty" Value="..."/>
...
</Style>
</UserControl.Style>
</UserControl>
A default Style in the UserControl's Resources should also work:
<UserControl x:Class="MyNamespace.MyControl" xmlns:local="MyNamespace" ...>
<UserControl.Resources>
<Style TargetType="local:MyControl">
<Setter Property="MyProperty" Value="..."/>
...
</Style>
</UserControl.Resources>
</UserControl>
You need to remove the x:Key from your defined style so that it can be applied universally to all controls of the same type as what is defined in the TargetType.
To quote from MSDN for Style.TargetType Property:
Setting the TargetType property to the TextBlock type without setting an x:Key implicitly sets the x:Key to {x:Type TextBlock}. This also means that if you give the [...] Style an x:Key value of anything other than {x:Type TextBlock}, the Style would not be applied to all TextBlock elements automatically. Instead, you need to apply the style to the TextBlock elements explicitly.
Necro answer for a special case. If the user control is selected via a DataTemplate resource in another WPF control or window, WPF may not automagically apply a default style from an imported resource dictionary. However, you can apply named style resource after importing a resource dictionary.
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Resources/ResourceDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<UserControl.Style>
<Binding Source="{StaticResource MyUserControlStyle}"></Binding>
</UserControl.Style>
To style all controls, add your ResourceDictionary to the resources of your App.xaml.
<Application.Resources>
<!-- Your Resources for the whole application here -->
</Application.Resources>
If your open your Mainwindow with the App...
<Application ...
MainWindow="MainWindow">
or during the startup event...
<Application ...
MainWindow="MainWindow">
Startup="Application_Startup">
the resources are available in every control of your MainWindow.
To set the style for a specific usercontrol look here:
Set Style for user control
in your user control xaml place the style inside the resources tag:
<UserControl>
<UserControl.Resources>
<Style ...</Style>
</UserControl.Resources>
//.. my other components
</UserControl>

Windows Style from ResourceDictionary don't apply

As I have multiple Windows in my application, I am looking for a solution that does not require me to set a binding on each Window.
I created a ResourceDictionary which has a style for the Window Background:
<Style TargetType="{x:Type Window}">
<Setter Property="Background" Value="AliceBlue"/>
</Style>
In my XAML, I set the ResourceDictionary:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Templates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
There is no error, but my Window color stays white.
This appears to be caused by a combination of the order in which WPF loads/processes styles from nested ResourceDictionary, and the specifics of the Window class.
Assume MainWindow is defined as per your post. Now put the following in Templates.xaml:
<Style TargetType="{x:Type Window}">
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="{x:Type Window}" x:Key="myStyle">
<Setter Property="Background" Value="Green"/>
</Style>
If MainWindow has no style defined, then you will see that in the designer it appears with a red background. The designer is parsing the whole Xaml and loading the resource dictionary, and then drawing the results. The style is read before the window is drawn, and so the red background is applied.
When you run the application, the window is created before the ResourceDictionary is applied. It looks for a default style (a style with x:Key="{x:Type Window}") before the nested ResourceDictionary is processed, and finds nothing. Therefore at runtime, the window appears with default colour. (This is the behaviour described in the comments above.) Remember that the style with x:Key="{x:Type Window}" has a default value that matches the Windows style.
This is borne out if you use myStyle explicitly. If you add to your Window definition the attribute Style="{StaticResource myStyle}" you'll find that the designer fails, but you also get a run-time error, because myStyle hasn't been created at the time that the Window needs it. If you switch to Style="{DynamicResource myStyle}" then you'll see that it works as you hope, because DynamicResource will update once the ResourceDictionary has been parsed and the style included.
So, applying this, you can fix the problem in one way by adding this to your Window element: Style="{DynamicResource {x:Type Window}}" - but this is cludgy. The better solution is to include your resource dictionary in the app.xaml file, where it will be parsed before any window is opened and thus available to all:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Templates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The real issue here is that your Window is not really a Window: it is a class that derives from Window and will in fact be MainWindow, Window2, etc... This means that the automatic style wireup for a Window will never work in this way, and some level of manual binding will unfortunately always be required.
This is the solution I used in my application. It lets me keep all my window styles together, and requires just a couple lines after the <Window.Resources> section.
Do your Style like so:
<Style x:Key="MyWindowStyle">
<Setter Property="Window.Background" Value="AliceBlue"/>
</Style>
Then, in your Window, after </Window.Resources> include the following:
<Window.Style>
<Style BasedOn="{StaticResource MyWindowStyle}"/>
</Window.Style>
Add a new brush in your resource dictionary
<SolidColorBrush x:Key="WindowBackground" Color="AliceBlue" />
and in your WPF window simply set the required resource to the window background property
<Window x:Class="GDD.Presentation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="300"
Background="{StaticResource WindowBackground}">

wpf silverlight multi-targeting ResourceDictionary

I'm writing some multi-targeting application (.net 4.0). I have problems with ResourceDictionay.
Scenario:
Create WPF CustomControlLibrary - name it "WpfLib", default Namespace "test"
In WpfLib create UserControl - name it "uc"
<UserControl x:Class="test.uc"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="res.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button Style="{StaticResource bStyle}" Content="Button" Height="23" Width="75" />
</Grid>
</UserControl>
Code for "res.xaml"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="bStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Red" />
</Style>
</ResourceDictionary>
Everything is great now....Button is Red
Now lets add new Project Silverlight Application and name it "SlApp" (Silverlight 5)(namespace "test")
Lets add "uc" from "WpfLib" as link("uc.xaml" "uc.xaml.cs" ).
Create new ResourceDictionary in "SlApp" and name it res.xaml like this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="bStyle" TargetType="Button">
<Setter Property="Background" Value="Blue" />
</Style>
</ResourceDictionary>
New ResourceDictionary has TargetType="Button" because x:Type is not supported in SilverLight. Background is set to color Blue not red.
And here starts the problem.
How do i make it work? Control uc displays error on merging(in Silverlight version). I need different ResourceDictionary on Wpf and Silverlight version of usercontrol. ClassLibrary doesn't support app.xaml and i can't use default style.

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

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.

Categories