I have a main Class (with an MainView.xaml) that dynamically loads various other Pages long after the MainView has been shown.
So MainView.xaml has following style defined:
<Window.Resources>
<Style x:Key="ErrorTemplate" TargetType="TextBox">
<Setter Property="FontSize" Value="30"/>
</Style>
</Window.Resources>
In one of the loaded pages I had following declaration:
<Page.Resources>
<Style x:Key="ErrorStyle" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ErrorTemplate"/>
</Style>
</Page.Resources>
This worked fine.
Now I needed to load other resources from an external XAML file so I used MergedDictionaries.
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Guaranteed to not have an ErrorTemplate key -->
<ResourceDictionary Source="MoreStyles.xaml"/>
<ResourceDictionary>
<Style x:Key="ErrorStyle" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ErrorTemplate"/>
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
And now I started to receive the message that ErrorTemplate could not be resolved.
Moving it outside of the MergedDictionary fixed the problem again.
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MoreStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ErrorStyle" TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate" Value="{DynamicResource ErrorTemplate"/>
</Style>
</ResourceDictionary>
</Page.Resources>
What is happening here?
So, today I installed MahApps in my WPF project. All went smoothly until I wanted to use the build-in styles.
This is my App.xaml:
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<BitmapImage x:Key="logoImage" UriSource="Images/Logo.png" />
<BitmapImage x:Key="profileButtonImage" UriSource="Images/ProfileButton.png" />
<BitmapImage x:Key="settingsButtonImage" UriSource="Images/SettingsButton.png" />
<BitmapImage x:Key="profileIconImage" UriSource="Images/profileIcon.png" />
<BitmapImage x:Key="listenIconImage" UriSource="Images/listenIcon.png" />
<BitmapImage x:Key="statsIconImage" UriSource="Images/statsIcon.png" />
<BitmapImage x:Key="accountButtonImage" UriSource="Images/accountButton.png" />
<BitmapImage x:Key="pauseButtomImage" UriSource="Images/pause-button.png" />
<BitmapImage x:Key="playButtomImage" UriSource="Images/play-button.png" />
<BitmapImage x:Key="stopButtomImage" UriSource="Images/stop-button.png" />
<BitmapImage x:Key="doneButtonImage" UriSource="Images/doneButton.png" />
<BitmapImage x:Key="arrowButtonImage" UriSource="Images/arrow.png" />
<BitmapImage x:Key="doneButtonHoverImage" UriSource="Images/doneButtonHover.png" />
<FontFamily x:Key="Novo">/Fonts/#Novecentosanswide-Medium</FontFamily>
<Style x:Key="ButtonStyle">
<Setter Property="Border.Background" Value="#262a33" />
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="True">
<Setter Property="Border.Background" Value="#1d2027" />
</Trigger>
</Style.Triggers>
</Style>
<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.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The BitmapImages are there for some of my buttons. My issue is that when I try to compile I get the following error:
All objects added to an IDictionary must have a Key attribute or some other type of key associated with them.
Each dictionary entry must have an associated key.
I installed all 3 of the MahApps NuGets, do you have any idea why these errors appear?
Wrap all the resources inside another ResourceDictionary and in that one add MahApp resources as MergedDictionaries
Thank's Ruben, work for me only wrap all resources inside ResourceDictionary
<Application.Resources>
<ResourceDictionary>
<!--Estilo Validação-->
<Style TargetType="TextBox">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<AdornedElementPlaceholder x:Name="placeholder"/>
<TextBlock FontSize="12" Foreground="Red"
Text="{Binding ElementName=placeholder,Path=AdornedElement.(Validation.Errors)[0].ErrorContent}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Red"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},
Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
<!--FIM Estilo Validação-->
<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.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
If I have a UserControl with the following two Labels inside of it's grid like so:
<Grid x:Name="mainGrid">
<Label x:Name="labelTitle"/>
<Label x:Name="labelValue"/>
</Grid>
Can I set their styles separately from within a ResourceDictionary something like:
<Style TargetType="{x:Type MyControl}">
<Style.Resources>
<Style TargetType="MyControl.mainGrid.labelTitle">
</Style>
<Style TargetType="MyControl.mainGrid.labelValue">
</Style>
</Style.Resources>
</Style>
If possible I would like to do all of this in the ResourceDictionary and not have to touch the UserControl at all.
Try using a trigger in the style based on the name.
App.xaml
<Application x:Class="WpfApplication34.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication34"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type local:MyControl}">
<Style.Resources>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}">
<Style.Triggers>
<Trigger Property="Name" Value="labelTitle">
<Setter Property="Content" Value="This is the Title" />
<Setter Property="HorizontalAlignment" Value="Left" />
</Trigger>
<Trigger Property="Name" Value="labelValue">
<Setter Property="Content" Value="This is the Value" />
<Setter Property="HorizontalAlignment" Value="Right" />
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
</Application.Resources>
</Application>
MyControl.xaml
<UserControl x:Class="WpfApplication34.MyControl"
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"
xmlns:local="clr-namespace:WpfApplication34"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid x:Name="mainGrid">
<Label x:Name="labelTitle" />
<Label x:Name="labelValue" />
</Grid>
</UserControl>
MainWindow.xaml
<Window x:Class="WpfApplication34.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"
xmlns:local="clr-namespace:WpfApplication34"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:MyControl />
</Grid>
</Window>
Screenshot:
I have a problem when I have several levels or resources in wpf
for instance if i have this code
main.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Style TargetType="{x:Type TextBox}" x:Key="Main">
<Setter Property="FontSize" Value="50"/>
</Style>
</ResourceDictionary>
sub.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Style TargetType="{x:Type TextBox}" x:Key="Sub" BasedOn="{StaticResource Main}">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="20"/>
</Style>
</ResourceDictionary>
all.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:p19"
>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Main.xaml"/>
<ResourceDictionary Source="Sub.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
app.xaml
<Application.Resources>
<ResourceDictionary Source="All.xaml"/>
</Application.Resources>
in mainwindow i just have
<Grid>
<TextBox Style="{StaticResource Sub}"/>
</Grid>
This won't work.
However if I put resources directly into app.xaml (and not through all.xaml) like this
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Main.xaml"/>
<ResourceDictionary Source="Sub.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
It does work. I think i remember that someone said somewhere (I can't remember where) that this is a bug in wpf and can be solved with some empty styles and with new .net framework.
I tried 2015 rc and 4.6 and it still doesn't work.
Does someone know how to fix it and where? And can they try out the code on their side to see if it works?
Thanks in advance for your help
The trick is to put this dictionary in turn into a merged dictionary:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="All.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Should work fine then.
Edit
However you get into trouble when you try to access a style from another dictionary. To get rid of this reference it in the sub.xaml too:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Main.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type TextBox}" x:Key="Sub" BasedOn="{StaticResource Main}">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="20"/>
</Style>
</ResourceDictionary>
I have a custom Calendar style and a custom DatePicker style.
Code in my MyCustomSkin.xaml (from my library project)
<Style TargetType="{x:Type Calendar}">
<Setter Property="Background" Value="Red"/>
</Style>
<Style TargetType="{x:Type DatePicker}">
<Setter Property="Background" Value="Green"/>
</Style>
They are both inside my MyCustomSkin.xaml ResourceDictionary (separate solution that generate a MyCustomSkin.dll) that I reference inside my application.
Code in my App.xaml (from my application)
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyCustomSkin;component/MyCustomSkin.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Code in my MainWindow.xaml (from my application)
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<Grid>
<DatePicker HorizontalAlignment="Right" />
<Calendar HorizontalAlignment="Left"/>
</Grid>
</Window>
When I create a Calendar in my application (without specifying any style), the background is red.
When I am creating a DatePicker in my application (without specifying any style), the background is green but the background of its calendar is the system one (=> not red).
Why? I thougt that I was overriding all the system calendars with mine. Why is it applying the custom style for the Calendar but not on the Calendar of DatePicker?
Thank you!
Your MyCustomSkin.xaml should be:
<Style TargetType="{x:Type Calendar}" >
<Setter Property="Background" Value="Red" />
</Style>
<Style TargetType="{x:Type DatePicker}" >
<Setter Property="Background" Value="Green" />
<Setter Property="CalendarStyle">
<Setter.Value>
<Style TargetType="{x:Type Calendar}" BasedOn="{StaticResource {x:Type Calendar}}"/>
</Setter.Value>
</Setter>
</Style>
DatePicker has a default CalendarStyle which will be applied on component initialization.