Metro Styles in resource dictionary - c#

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.

Related

UWP: application wide TextBlock foreground crashes app when set from static resource

I went through a lot of similar questions on SO, in regards to setting the foreground of a TextBlock through a static resource, but for whatever reason my UWP application keeps crashing on me.
I am starting to believe this is a limitation of UWP? Also, no stacktrace is generated from this.
I am using Microsoft Visual Studio Community 2022 v.17.2.6
ThemeColors.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="MyOffWhiteBrush" Color="#eeeeee" />
</ResourceDictionary>
TextBlockStyle.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource MyOffWhiteBrush}" />
</Style>
</ResourceDictionary>
App.xaml
<Application
x:Class="TestTextBlock.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestTextBlock">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ThemeColors.xaml" />
<ResourceDictionary Source="TextBlockStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainPage.xaml
<Page
x:Class="TestTextBlock.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TestTextBlock"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid>
<TextBlock Text="helloworld" />
</Grid>
</Page>
UPDATE #1:
If I change TextBlockStyle.xaml to this it works.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="_" />
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource MyOffWhiteBrush}" />
</Style>
</ResourceDictionary>
I don't understand why I need to declare an empty brush?
The reason for this behavior may be related to the Lookup behavior for XAML resource references and Forward references within a ResourceDictionary. You need to make sure the referenced resource must appear lexically before the resource reference when you use the resource.
I agree with #Mark W, the possible workaround is that you could define the basic resource on top of other resources.
In your scenario, it should be like this:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ThemeColors.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="{StaticResource MyOffWhiteBrush}" />
</Style>
I don't have the answer for why... In my application, I have a number of styles - separated out into color/brushes, sizes and layouts, and then default styles... for each dictionary that references other dictionaries, I include them at the top.
ColorsAndBrushes does not have any references.
SizesAndLayout does not have any references.
DefaultStyles references the two above.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorsAndBrushes.xaml" />
<ResourceDictionary Source="SizesAndLayout.xaml" />
</ResourceDictionary.MergedDictionaries>
so for my next layer, "NamedStyles", I have have the following to the top:
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ColorsAndBrushes.xaml" />
<ResourceDictionary Source="SizesAndLayout.xaml" />
<ResourceDictionary Source="DefaultStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
I don't know if this will work better for you, but maybe feels a little better than the random empty brush. And my app.xaml references all of them. This was build on a older (AnniversaryEdition) UWP SDK, so your mileage may vary.
Good luck!
-Mark

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

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.

Load control style from separate file in wpf

I have the following style added to my Windows.Resources
<Window.Resources>
...
<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="TitleText">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#90DDDD" />
<GradientStop Offset="1.0" Color="#5BFFFF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
...
</Window.Resources>
I have a lot of those styles in my xaml code and I would like to save each component style to an extra file (not an external file).. for example all the styles related to TextBlocks should be in a file called TextBlockStyles.xaml
How would I do this in wpf?
How do I link the style in my project ?
Thanks in advance
You use merged resource dictionaries
In you app.xaml you would use
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/Your.Assembly.Name;component/TextBlockStyles.xaml"/>
... other dictionaries here
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
or directly into a UserControl would be
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="/Your.Assembly.Name;component/TextBlockStyles.xaml"/>
... other dictionaries here
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
You can shorten Source="..." to just Source="TextBlockStyles.xaml" if the file is in the same assembly and in the root of the project, or alternatively Source="Styles\TextBlockStyles.xaml" if you put the resource dictionary into the folder Styles.
Use case: you have a user control called MyView.xaml with a button. You want to style the button with an external XAML file.
In MyView.xaml:
<User Control ...namespaces...>
<UserControl.Resources>
<ResourceDictionary>
...converters...
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyButton.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
...the rest of the control...
</UserControl>
In MyButton.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MSDNSample">
<Style x:Key="FooButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Pink" />
</Style>
</ResourceDictionary>
Back to MyView.xaml ("the rest of the control"):
<Button Style="{StaticResource FooButton}">
Hello World
</Button>
In Solution Explorer Right Click on your Project Select Add After that click on Resource Dictionary...
Choose name and add to your project.
Open App.xaml
Add This Code in Application Tag
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="YourStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
In YourStyle.xaml :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:APPNAME">
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Pink" />
</Style>
</ResourceDictionary>
you are looking for the dynamic resources. well the best way is to load and marge the dictionary in the resources. application or either on control page.
here is a good sample for it.
http://blogs.msdn.com/b/wpfsdk/archive/2007/06/08/defining-and-using-shared-resources-in-a-custom-control-library.aspx
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
this.Resources.MergedDictionaries.Add(Smyresourcedictionary);
Simply, go to your Window (example: MaindWindow.xaml) where you want to include the resource from the outer file and use MergedDictionaries principle to refer to that file:
<Window x:Class="UseMergedResource.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="600"
Width="600">
<Window.Resources>
<!-- DECLARING MERGED DICTIONARY -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source='Merged/BrushResources.xaml' />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<!---------------------------------->
</Window.Resources>
<StackPanel>
<Rectangle Width='200'
Height='100'
Fill='{StaticResource PrimaryBrush}' /> <!-- USAGE HERE -->
</StackPanel>
</Window>
From above Merged/BrushResources.xaml is the location of the resource file, which is located under the folder called Merged.
Now if you are wondering what should be the declaration syntax in the outer file, check this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- Location for application brushes -->
<SolidColorBrush x:Key='BorderBrush'
Color='Orange' />
<SolidColorBrush x:Key='HighLightBrush'
Color='LightBlue' />
<SolidColorBrush x:Key='PrimaryBrush'
Color='Pink' />
<SolidColorBrush x:Key='AccentBrush'
Color='Yellow' />
</ResourceDictionary>
If you want to make the resource available through all application (visible in all your windows) then declare in the App.xaml resources section.

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