In WPF, how can I cross-reference resources between ResourceDictionaries? - wpf

I work on a WPF project with many UserControls and I'm trying to put some sanity in my WPF resources.
A base file contains generic stuff needed by all views, such as colors:
<!-- Resources.xaml -->
<Color x:Key="FlashOrange">#F59500</Color>
Then, a resource file specific to a view needs to reference FlashOrange:
<!-- ContactViewResources.xaml -->
<DataTrigger Binding="{Binding IsActiveConversation}" Value="True">
<Setter Property="Background" Value="{StaticResource FlashOrange}"/>
</DataTrigger>
Finally I'd like to "include" both in my UserControl. Unfortunately, with this approach I get an exception about {StaticResource FalshOrange} not being defined.
<!-- ContactView.xaml -->
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Resources.xaml"/>
<ResourceDictionary Source="ContactViewResources.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
All the view files are in the same DLL assembly, and a separate EXE assembly runs
Thanks!

Either merge Resources.xaml into ContactViewResources.xaml, so the Static reference has a direct path to FlashOrange in its resource tree at load time, or use DynamicResource instead.

To reference one ResourceDictionary in another, use the MergedDictionary property of the ResourceDictionary that you want to hold the reference. In your case:
<!-- ContactViewResources.xaml -->
<ResourceDictionary ...>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="..\Resources.xaml"/>
</ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary>

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>

Mixing general WPF styles with ResourceDictionary

I came from web development and WinForms to WPF and maybe I didn't get the concept yet.
I'm able to define general styles for my Application in the app.xaml. For example I defined the style for all my ribbon controls in this file.
Then I tried Microsoft Blend and came across ResourceDictionary, which is somekind of Resource File .resx I knew from WinForms.
But as I see it's not possible to mix these two concepts. For example following xaml code will not work because ResourceDictionary have to be the only child.
<Application x:Class="Wpf.MyApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
StartupUri="MyMainWindow.xaml">
<Application.Resources>
<!-- Resources scoped at the Application level should be defined here. -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/RibbonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
<BitmapImage x:Key="IconDokumentNeu" >Images/NewDocument_32x32.png</BitmapImage>
<SolidColorBrush x:Key="LightGrayBrushKey">WhiteSmoke</SolidColorBrush>
</ResourceDictionary>
<Style TargetType="{x:Type ribbon:RibbonWindow}">
<Setter Property="Icon" Value="../time2_32.png" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
</Style>
</Application.Resources>
</Application>
It seems I didn't really get the concept. Maybe you can help me, why this is not possible and how I can use general styles next to ResourceDictionary.
You already have resources defined "next to" the dictionary, one image and one brush.
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Dictionaries from file here -->
</ResourceDictionary.MergedDictionaries>
<!-- Other resources here -->
</ResourceDictionary>
</Application.Resources>
Just include the {x:type} style in the resource dictionary
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- Dictionaries from file here -->
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type ribbon:RibbonWindow}">
<Setter Property="Icon" Value="../time2_32.png" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
</Style>
</ResourceDictionary>

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