Referencing a resource in a ResourceDictionary from a different ResourceDictionary in Silverlight - c#

I have the following set of code in my App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Client.Common;component/Theme/Brushes.xaml"/>
<ResourceDictionary Source="/Client.Common;component/Theme/Fonts.xaml"/>
<ResourceDictionary Source="/Client.Common;component/Theme/CoreStyles.xaml"/>
<ResourceDictionary Source="/Client.Common;component/Theme/SdkStyles.xaml"/>
<ResourceDictionary Source="/Client.Common;component/Theme/MyAppName.xaml"/>
<ResourceDictionary Source="/Client.Common;component/Controls/NavigationPanel.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
The NavigationPanel.xaml contains a style that looks like this:
<Style x:Key="NavigationPanelListBox" TargetType="ListBox">
<Setter Property="Background" Value="{StaticResource DarkBackground}" />
<Lots of XAML>
</Style>
The {StaticResource DarkBackground} is defined in the Brushes.xaml file (i.e. the first resource dictionary). It is defined as
<SolidColorBrush x:Key="DarkBackground" Color="#FF707176" />
in the resource dictionary.
At runtime, I get the following error:
Cannot find a Resource with the Name/Key DarkBackground [Line: 16 Position: 44]
The line numbers and position references the NavigationPanel.xaml resource dictionary in the app.xaml.
I can reference the brush from other controls, just not the included resource dictionary.
Why can I not reference or why does it not resolve the reference to a resource that is higher in the heirarchy of the merged resource dictionary?? What am I missing here?

Are you referencing the DarkBackground brush in any of the resources in the NavigationPanel dictionary?
If you are you might need to merge the Brushes resource dictionary into the NavigationPanel dictionary.
So in the NavigationPanel dictionary.
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Client.Common;component/Theme/Brushes.xaml" />
</ResourceDictionary.MergedDictionaries>

You can include one dictionary in another (like 'using' in C#) like so:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:Controls="clr-namespace:APC.IKM.UI.SL.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes.xaml"/>
<ResourceDictionary Source="Fonts.xaml"/>
<ResourceDictionary Source="CoreStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
Is this what you are looking for? The Cosmopolitan / Metro project template has a good example of this...

the trully answer is Eric's answer in this site: https://social.msdn.microsoft.com/forums/windowsapps/en-US/2be9a5f6-5313-448d-a9d9-296bac42215e/using-style-defined-in-merged-dictionary-from-another-merged-dictionary?forum=wpdevelop.
the Brushes.xaml and the NavigationPanel.xaml is parsed independently and then added to the merged dictionary of Application resources so they don't know anything about each other.

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

Merged Resource Dictionary folder of images in DLL not found

New to the WPF process here and trying to define a merged dictionary of a collection of merged dictionaries that are maintained in a utility DLL. I am attempting to resolve the resource location error.
Error
IOException: Cannot locate resource 'ui/wpf/imagelist16x16.xaml'
Theme.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/UI/WPF/ImageList16x16.xaml" />
<!--Future xaml file references-->
</ResourceDictionary.MergedDictionaries>
<Style x:Key="EmptyStyle"/>
</ResourceDictionary>
ImageList16x16.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:clr="clr-namespace:System;assembly=mscorlib">
<BitmapImage x:Key="Accept" UriSource="UI/Resources/Images16x16/accept.png"/>
</ResourceDictionary>
User Control Resource Reference
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/BHP_Utilities;component/UI/WPF/Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
When executed, the Theme.xaml is found as the error occurs based on the dictionary reference within it. The build option for both xaml files is Page and the Custom Tool property is set to XamlIntelliSenseFileGenerator.
Since the files are in the same folder, could you try removing "/UI/WPF/"
<ResourceDictionary Source="ImageList16x16.xaml" />

How do I set a primary color that I can use for my background property in ResourceDictionary

So I created a ResourceDictionary that looks like this
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="PrimaryColor" Color="#252525"/>
</ResourceDictionary>
Now my question is how do I get a hold of that key so I can use it for my background property on my MainWindow?
<Window ...
Background="{DynamicResource PrimaryColor}">
You need to merge the ResourceDictionary into your App.xaml:
<Application ...>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="YourResourceDict.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Once it's in scope, you could reference any resource using either {DynamicResource key} or {StaticResource key}
What's the difference between StaticResource and DynamicResource in WPF?

Organizing Xaml - Unable to apply StaticResource from different xaml file

I have a situation where the wpf application is not able to pickup StaticResource and instead fails with XamlParseException. But if I used a DynamicResource instead, the resource is found and no exception occurs.
I was trying to style and organize wpf resources as recommended at http://projekt202.com/blog/2010/xaml-organization/
I have 2 projects accordingly, a wpf control library that houses all resources and a main wpf project which uses those resources. Here is the structure of the 2 projects
Projects Structure
Wpf_Theme.ControlLibrary
--ResourceDictionaries
----BaseControlStyles
------ButtonStyle.xaml
------TextBoxStyle.xaml
----Brushes
------DefaultBlueTheme
----ResourceLibrary.xaml
Wpf_Theme.Main
--App.xaml
--MainWindow.xaml
Contents of xaml files
ButtonStyle.xaml
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource ControlBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource BorderColor}"/>
...
</Style>
DefaultBlueTheme.xaml (Brushes)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="PanelBackground" Color="#C8DCF0"/>
<SolidColorBrush x:Key="BorderColor" Color="#6A8FB5"/>
<SolidColorBrush x:Key="SelectedItemBackground" Color="Wheat"/>
<SolidColorBrush x:Key="TextForeground" Color="Black"/>
<LinearGradientBrush x:Key="ControlBackground" StartPoint="0,0" EndPoint="0,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0" Color="#DBECFD"/>
<GradientStop Offset="0.5" Color="#C7DBEF"/>
<GradientStop Offset="1" Color="#B0CAE5"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</ResourceDictionary>
ResourceLibrary.xaml (Merges all dictionaries in one file to be used by main project)
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes/DefaultBlueTheme.xaml"/>
<ResourceDictionary Source="BaseControlStyles/ButtonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
App.xaml (In Main project)
<Application x:Class="Wpf_Themes.Main.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="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/ResourceLibrary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="Wpf_Themes.Main.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<StackPanel Width="200" Margin="10">
<Button>Click Me</Button>
</StackPanel>
</Window>
As stated earlier in the post, I am not able to resolve the style(Background and Border brushes) for the Button using the StaticResource applied in ButtonStyle.xaml. If I use DynamicResource instead, the brushes are found correctly and applied to the Button. Any insights why this behavior occurs.
Edit:
Following Mike's suggestion, I included the xaml files from the Wpf_Theme.ControlLibrary project directly into the App.xaml of the Main project like below
App.xaml
<Application x:Class="Wpf_Themes.Main.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="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/Brushes/DefaultBlueTheme.xaml"/>
<ResourceDictionary Source="/Wpf_Themes.ControlLibrary;component/ResourceDictionaries/BaseControlStyles/ButtonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
and resources are now located correctly using the StaticResource
Static resource references are resolved at parse time (for the most part), whereas dynamic references are resolved at run time. This means a static reference can only be used if the resource has been parsed before the reference, whereas a dynamic reference can be used as a forward reference for a resource that is defined later.
Source: http://drwpf.com/blog/category/resources/
When the two ResourceDictionaries are in a separte Assembly and you reference them at the same time I would guess that this processing happens at the same time. Whereas if you load them in App.xaml directly it is ensured that they are loaded in the right order.
So the Resources of your first Dictionary are not available to the second Dictionary since you include them in the same Dictionary.
There is two ways to solve the Problem. Either you use DynamicResources which are evalutated at runtime (like you already tried).
Another solution if you now the hyrachie of your Resource Dictionaries you can do several levels. Like:
<Application x:Class="WPF_Theme.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:,,,/ControlLibrary;component/ResourceDictionaries/BaseLevel.xaml" />
<ResourceDictionary Source="pack://application:,,,/ControlLibrary;component/ResourceDictionaries/SecondLevel.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
BaseLevel.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes/DefaultBlueTheme.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
SecondLevel.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="BaseControlStyles/ButtonStyle.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
DefaultBlueTheme.xaml and ButtonStyle.xaml stays unchanged.
With this you would ensure that the different ResourceDictionaries are already there if you need them.
I hope that helps.

Converting WPF local resource to application resource

I have a local resource in XAML and I want it to be used by other parts of the code. How can I make it "global" (i.e. an application-wide resource)? Here is my local resource:
<ResourceDictionary >
<local:BoolToLightConvertor x:Key="LightConverter" / >
</ResourceDictionary>
How can I put this in the App.xaml?
Application Resources
In addition to defining resources at the level of the element or Window, you can define
resources that are accessible by all objects in a particular application. You can create an application
resource by opening the App.xaml file (for C# projects) or the Application.xaml file
(for Visual Basic projects) and adding the resource to the Application.Resources collection, as
shown here:
<Application x:Class="WpfApplication.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<SolidColorBrush x:Key="appBrush" Color="LightConverter" />
</Application.Resources>
</Application>
Create a file (e.g. SharedResources.xaml) as follows:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Your.Namespace.Here;assembly=Your.Assembly.Here">
< local:BoolToLightConvertor x:Key="LightConverter" / >
</ResourceDictionary>
In your App.xaml add the following lines:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="SharedResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</Application.Resources>
You can now use this converter from within the XAML
(The <Style TargetType="{x:Type Rectangle}"/> is a workaround to stop a WPF bug ignoring your resource dictionary and was recommended by another question here on SO. The link unfortunately eludes me now though)

Categories