WPF ResourceDictionary and DynamicResource - wpf

i am new to WPF so maybe this will be "noob" question but i can't find answer to it (and it seems so easy)...
well i am programing WPF app and i want to use smth similar to css for webpages, so i found ResourceDictionary and tried to use it...
I have main window in which i create Frame and on click some UserControl is loaded to that same Frame.I include my ResourceDictionary (root/style/Styles.xaml) to my main window like this:
<Window.Resources>
<ResourceDictionary x:Key="styles" Source="style/Styles.xaml" />
</Window.Resources>
in which i have:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ProductsRequired" TargetType="{x:Type Label}">
<Setter Property="Height" Value="28" />
...
I don't use it on my main window but want to use it on my UserControls, which are loaded to that main window and i try to use it like this:
<Label Name="product1" Style="{DynamicResource ProductsRequired}" />
Warning i am getting all the time is: The resource "ProductsRequired" could not be resolved.
I even tried including Styles to my UserControl
<UserControl.Resources>
<ResourceDictionary x:Key="styles" Source="../style/Styles.xaml" />
</UserControl.Resources>
and nothing happens...
Well my question is long but i wanted to be clear... :)
P.S. all that logic works in C# code btw
private ResourceDictionary myStyles = new ResourceDictionary();
Style ProductsRequired = myStyles["ProductsRequired"] as Style;
product1.Style = ProductsRequired;

This won't do, you add a resource dictionary as a resource when you need to add it to the resources, it cannot be accessed like this. You need to add it to the MergedDictionaries (See MSDN for usage examples!).

are you referencing the correct assembly?
for example:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SecurityManagerResources;component/DictionarySecurityResources.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>

You need to do this
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="style/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>

Related

xaml ResourceDictionary inside User Control Library

how is it possible to define a ResourceDictionary inside a User Control Library and access them via Xaml-Code.
I've created something like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
>
<Style x:Key="NormalStyle" TargetType="{x:Type Control}">
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontFamily" Value="Arial" />
<Setter Property="FontStyle" Value="Normal" />
</Style>
.
.
.
</ResourceDictionary
And now I want to use this "NormalStyle" with a Control
Style="{StaticResource NormalStyle}"
But Visual Studio says "The resource "NormalStyle" could not be resolved."
Did i miss or forget something?
Thanks for helping me
You will have to include or merge your ResourceDictionary with UserControl.Resources like below. Here in Source give path to your ResourceDictionary.
<UserControl.Resources>
<ResourceDictionary Source="MyResourceDictionary.xaml"/>
</UserControl.Resources>
OR
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyResourceDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Then you can use the resources in the dictionary inside your UserControl
Style="{StaticResource NormalStyle}"
Please add style reference in App.xamal therfore so that it loads when you run the application.
When you add any external resource file you need to add it in App.xamal to get it's reference in your app else you need to manually add reference to every xamal form to access style and templates
This is how you going to add it in App.xamal using MergedDictionaries than where ever you refer any style in you application it will have it's reference
<ResourceDictionary.MergedDictionaries>
<!--
Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Common/CommonStyles.xaml"/>
<ResourceDictionary Source="Project/Common/CommonStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
Hope that helps
Alright, so I got it half to work. Inside my UserControlLibrary i made a new Xaml-File "UIStandards", where put all my Styles into. Now in my Main Project, i want to have access to these Styles and I think i should use a MergedDictionary.
What i did was this:
<Application x:Class="MentorPlusClientWindowsWPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MentorPlusClientWindowsWPF"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Dialog="clr-namespace:MahApps.Metro.Controls.Dialogs;assembly=MahApps.Metro"
Startup="Application_Startup">
<!--StartupUri="MainWindow.xaml"-->
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/CrossProjectUserControls;component/UIStandards.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
As you can see, i referenced the UISTandards.xaml but inside a UserControl inside my MainProject, none of my Styles can be found.
Any solutions?

How should application wide resources be organized?

Here is the scenario:
I have been using VS 2010 to write quite a large WPF project using MEF. There are multiple projects within this solution and I have one ResourceDictionary for all of my styles.
The AppStyles.xaml ResourceDictionary is located in my startup project, it contains all of my styles for the project. And within my App.xaml I have the following:
<Application x:Class="Dionysus.Shell.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DispatcherUnhandledException="UnhandledException" ShutdownMode="OnMainWindowClose">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppStyles.xaml"/>
</ResourceDictionary>
</Application.Resources>
Now, this all works perfectly in design mode of VS 2010 and when I am debugging, the correct styles are being applied to all of my controls. But I recently switched to VS 2012, and the designer is no longer working! When I debug it works perfectly but whenever I use one of my styles as follows:
<Button Name="btnForward" Height="23" Margin="10,0" Style="{StaticResource DionysusButton}" Grid.Row="2" Grid.Column="0"/>
I get the following error in the VS 2012 designer:
The resource "DionysusButton" could not be resolved.
I am clueless as to why this is happening, I have renamed my Style, and even the ResourceDictionary to no avail.
Is there a different way I should be doing this in VS 2012 or is this a problem with VS 2012?
I have found a lot of posts that say that changing the x:Name property of my AppStyles.xaml ResourceDictionary to x:Key will resolve this problem but I cannot do that as it is not a valid option for a ResourceDictionary.
Thanx in advance
-- UPDATE
I am using Marc's answer and all seems to be going well except for default styles. I have the following style:
<Style TargetType="DataGrid" x:Name="DataGridStyle"/>
And this is my main ResourceDictionary:
<ResourceDictionary x:Name="Main"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/AppStyling.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="DataGrid" BasedOn="{StaticResource DataGridStyle}"/>
When I do not add the Style tag in my main ResourceDictionary it works fine, but the style is not being applied to all items obviously. When I do add it, i get the following exception:
Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception
Ideas?
Are you trying to use the styles which are located in your app.xaml in your modules which you export into the shell using PRISM? The modules should not have a reference to your application/shell project (the startup project)? Then they maybe just don't 'know' the project, which contains the styles? Though the question is why it works in VS2010 then... Please let me know, if I misunderstood your MEF scenario, I'll adapt my answer then.
Resources and Prism is abit tricky, and I am a fan of the following approach, which I have posted before, but it might help in your case too. It is much more appropriate for a PRISM solution than placing your resources inside app.xaml:
I usually create a seperate styling project, which I reference from the projects, which I want to style. The styling project has a fixed structure like this:
For every control, I create a styling ResourceDictionary. For example for my buttons:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="PrimaryButtonStyle" TargetType="Button">
</Style>
<Style x:Key="ToolbarButton" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="3"/>
<Setter Property="Background" Value="Transparent"></Setter>
</Style>
</ResourceDictionary>
In one main ResourceDictionary, I merge all the other dictionaries, in this case in the file IncaDesign.xaml, which you can see in the picture above:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Commons.Controls;assembly=Commons">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Converter/Converter.xaml" />
<ResourceDictionary Source="Styles/Button.xaml" />
<ResourceDictionary Source="BitmapGraphics/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Default Styles -->
<Style TargetType="Button" BasedOn="{StaticResource PrimaryButtonStyle}"></Style>
</ResourceDictionary>
Notice how I defined the default styles, which are applied automatically, unless you specify otherwise. In every window or control, that you want to style, you only need to reference this one ResourceDictionary. Note the definition of the source, which is a reference to the assembly (/Commons.Styling;component...)
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Commons.Styling;component/IncaDesign.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- Here you can added resources which belong to the UserControl only -->
<!-- For example: -->
<DataTemplate x:Kex="UcTemplate" />
</ResourceDictionary>
</UserControl.Resources>
Default styles will be set automatically now, and if you want to access a resource explicitly, you can do this, using StaticResource.
<Viewbox Height="16" Width="16" Margin="0,0,10,0">
<ContentControl Content="{StaticResource FileIcon32}" />
</Viewbox>
This is very nice solution in my opinion, which works for very complex solutions, including modular solutions, for example built with PRISM.

Using Styles in merged ResourceDictonaries in Silverlight 5

I've got a bunch of styles in my app.xaml and they are all being used just fine in my pages within my SL5 app. I'd like to move these styles to multiple resource dictionaries to make it more manageable and consumable.
First I copied a style to a new resource dictionary in the /Styles/ButtonStyles.xaml page in my project... a snippet looks like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="RegistrationsRolloverImage" TargetType="Button">
<Setter Property="Template">...</Setter>
</Style>
<Style x:Key="FinancialLedgerRolloverImage" TargetType="Button">
<Setter Property="Template">...</Setter>
</Style>
</ResourceDictionary>
Next I added the following to my App.xaml:
<ResourceDictionary x:Key="MergedStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
It forced me to add a x:key to the ResourceDictionary tag as I kept getting a build error. Now it builds, but the buttons that use the style aren't getting the style. In fact I'm getting a JS error that it can't find a style with the name of the two styles in my resource dictionary. They work just fine if they are in the App.xaml, but not if they are in seperate resource dictionary. I reflected the generated DLL and can see the styles/buttonstyles.xaml in the DLL.
At a loss... and can't figure out what's wrong. Ideas?
Are they within the same project? Try something more like this in your app.xaml;
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/YourResDictionaryContaining.Proj.Name;component/Styles/ButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
I have to do this to have consolidation of resourcedict's stored in one project, and then add that to the app.xaml of each other project to make them available globally. Currently I run about 6 Resource Dicts acros 20 projects in the same solution this way and it works great.
In the full App.xaml sample you want use "local" resources.
But when you have "local" resources and you want to merge a resource directory the systax a little bit different.
Try it like this:
<Application ...>
<Application.Resources>
<ResourceDictionary>
<vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="BaseTextBlock" TargetType="TextBlock">
...
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>

Xaml Design View can't find Background Brush

in order to clean up my code, I'm trying to split my app.xaml into seperate resource dictionaries. This works at runtime, but not at design time:
snipped in app.xaml
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/;component/Theme/Colors.xaml" />
<ResourceDictionary Source="/;component/Theme/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Colors.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="backgroundBrush" Color="Gold"/>
</ResourceDictionary>
Styles.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="StatusBar">
<Setter Property="Background" Value="{StaticResource backgroundBrush}" />
</Style>
</ResourceDictionary>
Snipped of MainWindow.xaml
<Window x:Class="test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="test" Width="800" Height="600" >
<StatusBar Name="statusBar" DockPanel.Dock="Bottom">
<StatusBarItem Content="{Binding statusMessage}" />
</StatusBar>
DesignView gives the error:
Error 8 '{DependencyProperty.UnsetValue}' is not a valid value for property 'Background'. C:\Daten\DotNet\test\test\MainWindow.xaml 123
If I put backgroundBrush directly into app.xaml like so:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/;component/Theme/Colors.xaml" />
<ResourceDictionary Source="/;component/Theme/Styles.xaml" />
<ResourceDictionary>
<SolidColorBrush x:Key="backgroundBrush" Color="Gold"/>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
DesignView has no problems.
So is there a way to tell DesignView where to find backgroundBrush, if this brush is placed into a seperate resource dictionary?
Thats the problem with StaticResource isnt it. It needs the resource key resolved explicitly using shared \ merged \ direct resource dictionaries hierarchically up.
There are two options...
merge Colors.xaml dictionary in Styles.xaml
OR
in Styles.xaml refer the bursh using DynamicResource.
In case Resources are in different assemblies than that where MainWindow resides and the one dictionary is refering to the other dictionary. In that case reference is not resolved. This bug is already reported at Microsoft site in case your target framework is 4.0. However they have provided a workaround for it. Simply add the empty style in your Resource dictionaries and it will work fine like this -
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/;component/Theme/Colors.xaml" />
<ResourceDictionary Source="/;component/Theme/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Window}"/>
</ResourceDictionary>
</Application.Resources>
For further refernce please look at this link - https://connect.microsoft.com/VisualStudio/feedback/details/555322/global-wpf-styles-are-not-shown-when-using-2-levels-of-references#details
Try
{StaticResource ApplicationPageBackgroundThemeBrush}
for your status bar background value

WPF resource merged to Application.Resources but not resolved at runtime

I have a brush that is part of a ResourceDictionary that is merged to Application.Resources.
But for some reason it's not resolved at runtime when a style is being applied to one of the controls. However, if I call Application.Current.FindResource("BrushName") from the Immediate Window at the time when exception is thrown, the resource is found.
Am I missing something? Isn't WPF supposed to try to look for the resource in the app's resources?
UPDATE
The application is quite big, so I can't post all actual code but here's the way the resources are merged and used:
Brushes.xaml
<ResourceDictionary ...>
<SolidColorBrush x:Key="BrushName" Color="#12345678" />
</ResourceDictionary>
SomeStyles.xaml
<ResourceDictionary ...>
<Style x:Key="SomeStyle">
<Setter Property="SomeProperty" Value="{StaticResource BrushName}" />
</Style>
</ResourceDictionary>
App.xaml
<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes.xaml" />
<ResourceDictionary Source="SomeStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application ...>
And then some control might use the style using the resource like this:
...
Style={StaticResource SomeStyle}
...
UPDATE
It seems to happen to menus and controls that are created in code. Can it be related to those controls and menus not being parts of any window's visual tree?
Your SomeStyle.xaml dictionary needs to reference Brushes.xaml dictionary directly, like so:
<ResourceDictionary ...>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style x:Key="SomeStyle">
<Setter Property="SomeProperty" Value="{StaticResource BrushName}" />
</Style>
</ResourceDictionary>
StaticResources only search up the tree of the current dictionary, so you need to pass in any resources that it needs to reference.
Are you using DynamicResource in the XAML mark up extension?
Your xaml should be {DynamicResource brushName} not {StaticResource brushName}

Resources