Style based on StaticResource previously defined is not found at runtime - wpf

I'm using Telerik's RadControls for WPF with implicit styling. The following style is defined in Themes/Windows8/Telerik.Windows.Controls.RibbonView.xaml:
<Style TargetType="telerikRibbonView:RadRibbonView" x:Key="RadRibbonViewStyle">
...
</Style>
My own styles and the Telerik default ones get merged like this in the assembly Lib.Windows.Controls in the folder Themes:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Windows8/Telerik.Windows.Controls.RibbonView.xaml" />
<ResourceDictionary Source="MyTheme/TelerikCustomizations.xaml" />
<ResourceDictionary>
<!-- avoid optimization -->
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
And in TelerikCustomizations.xaml I define the following (empty, for testing purposes) style:
<Style x:Key="MyThemeRadRibbonViewStyle" TargetType="{x:Type telerik:RadRibbonView}" BasedOn="{StaticResource ResourceKey=RadRibbonViewStyle}" />
Which results in the following exception at runtime:
'Provide value on 'System.Windows.Markup.StaticResourceHolder' threw an exception.' Line number '4' and line position '42'.
{"Cannot find resource named 'RadRibbonViewStyle'. Resource names are case sensitive."}
Which led me to the following debugging statements in MyView.xaml.cs:
public ShellView()
{
var baseStyle = FindResource("RadRibbonViewStyle");
var inherited = FindResource("MyThemeRadRibbonViewStyle");
InitializeComponent();
}
Now the thing is: The exception is thrown on the second FindResource call. With the exact same message. However the RadRibbonViewStyle is clearly found in the first line of the constructor.
If it matters, the merged dictionary is actually merged in App.xaml a second time.
I'm sure I'm missing something obvious, but I can't figure out what.
App.xaml
<Application x:Class="TestClient.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Views/ShellView.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Lib.Windows.Controls;component/Themes/MyTheme.xaml" />
<ResourceDictionary>
<!-- added to avoid optimization -->
<Style TargetType="{x:Type Rectangle}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs does not overwrite the constructor. In fact it does not do anything.
Update
If I merge the Telerik dictionaries in TelerikCustomizations.xaml instead of merging them in yet another dictionary (MyTheme.xaml), the exception disappears.
However, I'd still like to know why this happens.

You need to merge in the Windows8/Telerik.Windows.Controls.RibbonView.xaml in your MyTheme/TelerikCustomizations.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Windows8/Telerik.Windows.Controls.RibbonView.xaml" />
<ResourceDictionary>
<Style x:Key="MyThemeRadRibbonViewStyle" TargetType="{x:Type telerik:RadRibbonView}" BasedOn="{StaticResource ResourceKey=RadRibbonViewStyle}" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
And now you can use/merge this dictionary wherever you want.
You need to do this because StaticResource is not working between "sister" MergedDictionaries so you cannot reference a resource which was merged on the same level because the StaticResource looks only backwards to the direct parents:
From MSDN:
XAML resource references within a particular resource dictionary must
reference a resource that has already been defined with a key, and
that resource must appear lexically before the resource reference.
Forward references cannot be resolved by a XAML resource reference
But when using MergedDictionaries:
In the resource-lookup sequence, a MergedDictionaries dictionary is
checked only after a check of all the keyed resources of the
ResourceDictionary that declared MergedDictionaries.

Related

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>

WPF ResourceDictionary and DynamicResource

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>

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

How to apply theme in component designer just like that in application project designer implicitly?

Say i had a theme file Button.xaml for standard button.
By merged in application resource dictionary it can implicitly applied in application project designer.
But after i move Button.xaml to component project, the component project designer can not implicitly apply the theme file.
How can i make that theme file works implicitly in component project ?
Update:
the Themes.xaml as follow
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/StyleLibrary;component/Themes/Shared.xaml" />
<ResourceDictionary Source="pack://application:,,,/StyleLibrary;component/Themes/Button.xaml" />
<ResourceDictionary Source="pack://application:,,,/StyleLibrary;component/Themes/ComboBox.xaml" />
...
<Application x:Class="ButtonStyleTest.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:,,,/StyleLibrary;component/Themes.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
If i use merged Theme.xaml, the Button look normal in designer, but failed in runtime.
But if i merge Button.xaml, ComboBox one by one, it look normal for both design and runtime.
New example.
Say that you have a Library called StyleLibrary.
In this Library you have a ResourceDictionary called Button.xaml which looks like this
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type Button}" >
<Setter Property="Width" Value="75" />
<Setter Property="Height" Value="23" />
</Style>
</ResourceDictionary>
In the Application we then add a reference to StyleLibrary and in App.xaml we add this.
<Application x:Class="ButtonStyleTest.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:,,,/StyleLibrary;component/Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
This style will apply in the Application and in the Libraries both in runtime and in designer.
To the left is my MainWindow. Is has one Button of its own, and then a UserControl from TestLibrary that has two Buttons. To the right is a Window from TestLibrary which contains one UserControl from TestLibrary, all Buttons seem to have the style applied.

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