I have a Project, where I am using prism for Navigation between usercontrols.
The App.xaml has some Definition for resources:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Resources/GlobalResources.xaml" />
<ResourceDictionary Source="pack://application:,,,/Resources/Themes/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
These are applied during design time and everything Looks the way it's supposed to. As I run the application the resources are not applied anymore. Resources referenced by key Work fine (e.g. BoolToVisConverter), but Resources applied to control types are ignored.
Important
The assumption made in the last sentence of the question is wrong.
Nothing is ignored during runtime - it's ignored during design time.
After Investigation of the problem, it has nothing to do with the merged dictionaries, nor with resources not being applied during runtime.
The problem arises through a definition of a style for TextBlock:
<Style TargetType="TextBlock">
<Setter Property="Margin" Value="2,2,3,2" />
</Style>
This style will be ignored during design time, but applied in runtime - thus leading to a different layout.
Adding explicit keys for resources or anything else are not necessary.
For testing purposes, if an design is applied or not just add some silly text-color or something like that - if I'd done that early, I would have found the problem in a jiffy.
Related
So we are trying to retemplate some stock wpf controls by changing their default styles in the generic.xaml
When we normally do this we subclass a control and then override the default style key of the subclassed control in its static initializer. However, we are trying to just override the basic control now without subclassing it. That way anyone in the company using the stock wpf control will get our new styling by default.
I can't seem to get this to work though.
In my sandbox application which is a watered down version of our actual problem, I have the following.
MainWindow.xaml
<StackPanel>
<TextBlock>It doesn't work</TextBlock>
<local:CustomTextBlock>It works</local:CustomTextBlock>
</StackPanel>
Themes/Generic.xaml
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="100" />
</Style>
<Style TargetType="{x:Type test:CustomTextBlock}">
<Setter Property="FontSize" Value="100" />
</Style>
CustomTextBlock.cs
public class CustomTextBlock : TextBlock
{
static CustomTextBlock()
{
Type _CustomTextBlock = typeof(CustomTextBlock);
DefaultStyleKeyProperty.OverrideMetadata(
_CustomTextBlock,
new FrameworkPropertyMetadata(_CustomTextBlock));
}
}
Which results in this being displayed.
My theory is that the WPF engine is ignoring our style because the default style key is either A: not overridden or B: is finding their style in their generic.xaml first.
My question is, is there a work around for this? Are my assumptions correct?
UPDATE:
According to reference source, the default style key is overridden in the stock wpf control for TextBlock.cs in this case
Reference Source TextBlock.cs (Line 346)
To accomplish this, you can put your styles either directly into App.xaml or into a separate ResourceDictionary (named DefaultStyles.xaml).
Putting directly into App.xaml is easy enough, just put the style within the Resources element.
If you want to put the styles into a file (this is useful if you want the styles for multiple applications or within multiple assemblies) you add it to the MergedDictionaries of your App.xaml as such
<Application x:Class="MyAwesomeApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/DefaultStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
This assumes that you put the file DefaultStyles into the Themes folder. If it is in another assembly you would do the following:
<ResourceDictionary Source="/Company.Controls.UI;component/DefaultStyles.xaml"/>
Have a look at this post (What is so special about Generic.xaml).
The main issue seems to be:
WPF looks for the default style in a special resource dictionary in the Themes folder in the same assembly as the control.
'Your' control is defined in 'your' assembly, TextBlock is defined in PresentationFramework. So you better create another ResourceDictionary for re-styling standard controls and include/merge it in each of your xaml documents (I suppose, this hurts).
Hope it helps.
I am having a nagging issue with my App.Resources MergedDictionary. Every time add a new dictionary with a source and XML namespace from another assembly, an error is produced and I cannot build my program.
The error appears in App.xaml with the ResourceDictionary underlined and the message Value Cannot be Null. Parameter Name: item. This makes absolutely no sense as I have done the exact same thing before. The only difference is that this time, I am referencing the namespace of another assembly(c# class library). Here is the App.xaml file:
<Application x:Class="Quiz.Client.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Quiz.Client"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles.xaml" />
<ResourceDictionary Source="Resources/Templates.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Below is Styles.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Quiz.Client">
<Style x:Key="StrongFont"
TargetType="ContentControl">
<Setter Property="FontSize"
Value="20" />
<Setter Property="FontWeight"
Value="ExtraBold" />
<Setter Property="Foreground"
Value="DarkRed" />
</Style>
</ResourceDictionary>
Here is Templates.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Quiz.Client"
xmlns:domain="clr-namespace:Quiz.Core.Domain;assembly=Quiz.Core"
xmlns:common="clr-namespace:Quiz.Client.Common">
<DataTemplate x:Key="ArithmeticQuestionTemplate"
DataType="domain:ArithmeticQuestion">
</DataTemplate>
<common:QuestionTemplateSelector x:Key="QuestionTemplateSelector"
ArithmeticTemplate="{StaticResource ArithmeticQuestionTemplate}" />
</ResourceDictionary>
What the heck is going on? Was there a software-breaking change introduced or something? I am completely lost.
Confirm!!! This bug is tracked by Microsoft. This mean WPF in some points will is trying to report to Microsoft automatically with Microsoft report process. During the report VS start freeze. Please, wait bug report to finish.
The bug still exist in lattes VS 2019.
After restart everything is fine. Confirm!!!
Thanks for the answer. I believe it is a Visual Studio bug caused by something unknown. Maybe one of my plugins, who knows. The only thing that fixes the issue is restarting visual studio and building the project. The problem seems to begin when adding a new namespace from another assembly. The project then can't build until visual studio is restarted. Very weird, never seen anything like it before. – user3096803
Not sure why your method isn't working but it's not how I usually import resources myself. Typically I'll add a ResourceDictionary to my library project, put all the libraries resources in that and import it into my main project using pack syntax:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MyLibrary;component/LibraryResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<!-- main project resources go here -->
</ResourceDictionary>
In general I'd argue that this is a better architecture anyway as it doesn't require a re-compile of your main project each time one of the child library resources change. It also makes it easier later on if you decide to switch to MEF, as your library resources are now encapsulated in a single ResourceDictionary object that you can readily [Export].
I don't really understand the answer from #Pit but I tried restarting visual studios and also changing all source paths to full pack URIs, and nothing seemed to work. Came across this thread that hinted at using Tools > Options > Preview Features > New WPF XAML Designer for .NET Framework which fixed the issue for me.
EDIT: This "fix" may have been a red herring, it still had issues but they were equally cryptic! After switching back to the old XAML designer and doing some further digging I found that one of my merged dictionaries was incompatible with the wpf designer and it was resulting in this error. The fix on that page resolved my issue.
This specific fix probably won't help anyone, but hopefully the methodology will. Check if there are any errors in any of the individual resource dictionaries in the merged dictionaries.
I'm trying to make use of the SharedResourceDictionary from this tutorial. This class derives from ResourceDictionary, but loads content only once even if it is referenced multiple times. It works like a charm when I build and run it.
However, any styles referenced using a SharedResourceDictionary will cause a compiler error in the XAML designer:
The resource "X" could not be resolved.
This error does not occur when I simply switch SharedResourceDictionary to ResourceDictionary.
The reference {StaticResource LightGreenBrush} in the following example will cause an error, even though it is defined in ColorDictionary.xaml:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<SharedResourceDictionary Source="pack://Application:,,,/MyAssembly;component/ResourceDictionaries/ColorDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource LightGreenBrush}"/>
</Style>
</ResourceDictionary>
Is there any way to prevent this error from showing on (what seems to be) perfectly valid XAML?
I'm at my ropes end with this. I have spent countless hours trying to figure this out and no such luck.
Short Explanation of Problem
Inside my custom control class, when I check Application.Current.Resources["key"] I am returned null. This "Key" style is inside a local dictionary which is supposed to be merged with the Application.Current.Resources by my Control Library's themes/generic.xaml resource.
How do I reference/confirm a reference to a MergedDictionary in my SilverLight Control Library's themes/generic.xaml.
Is this even possible or is my thinking on how merged resources are suppose to be merged entirely wrong?
Please help. Thanks in advance.
Long Explanation of Problem
I have a Silverlight Control Library with a Controls folder, and a Themes folder. Inside the Themes folder I have generic.xaml. Its content:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SilverLightLib;component/Themes/EnhancedLabelDict.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Inside the Themes folder I have EnhancedLabelDict.xaml. Its content:
<Style x:Key="ReadOnlyTextBox" TargetType="TextBox">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Background" Value="#FFFFFFFF"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="2"/>
<Setter Property="BorderBrush">
<!-- A lot more code -->
</Style>
Both these files build action is set to Page.
Now I have no idea if the generic.xaml is even loading my resource. The only way I can tell is if I put some un-formatted text between . This causes an error.
If I use an incorrect path to my ResourceDictionary, I receive a run time error - 'Failed to assign to property 'System.Windows.ResourceDictionary.Source'
Inside my Controls folder, I have EnhancedLabel.cs which extends ContentControl. Inside it's constructor, I create a new TextBox and assign it's style like so:
Style style = Application.Current.Resources["ReadOnlyTextBox"] as Style;
this.textBox.Style = style;
I have this style in both the App.xaml and my EnhancedLabelDict.xaml which is inside my library. When I comment out the Style in App.xaml, the 'ReadOnlyTextBox' style is not found (null). Uncomment it, it is found.
I don't understand why I cannot reference my style from within my EnhancedLabel.cs.
If I take the EnhancedLabelDict.xaml, add it to a Themes folder inside a Resources folder inside my main Application. If I then add the following to my App.xaml:
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SilverLightPOC;component/Resources/Themes/EnhancedLabelDict.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
My control works! So other than the path, there is nothing different. But this doesn't work because I don't want to have to store Dictionary files that my Library depends on, inside the main application.
Please help.
There is an optimization bug in Silverlight when you have more than 3 levels deep of nested dictionaries - they're not loaded unless you use a workarround.
See
Adding a Merged Dictionary to a Merged Dictionary
In a WPF application I defined default control styles in separate resource dictionaries (e.g. "ButtonStyle.xaml"), and added them as merged dictionaries to a resource dictionary named "ResDictionary.xaml".
If I refer this "ResDictionary.xaml" as merged dictionary in my App.xaml, the default styles are not applied. However, if I refer the "ButtonStyle.xaml", it works correctly.
If I recompile the same code in .NET 3.5 or 3.0, it recognizes and applies the default styles referred in "App.xaml" through "ResDictionary.xaml", but not in .NET 4.0.
At runtime if I check the Application.Current.Resources dictionary, the default styles are there, but they are not applied, only if I specify the Style property explicitly in the Button control.
Are there any solutions to refer a resource dictionary (containig default styles) this way in .NET 4.0?
App.xaml:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ResDictionary.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
ResDictionary.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Default/ButtonStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
ButtonStyle.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="Button">
<Setter Property="Background" Value="Yellow"/>
</Style>
</ResourceDictionary>
The best solution is to add a dummy default style in the resource dictionary where you merge all resources together.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Style/Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="Control" BasedOn="{StaticResource {x:Type Control}}" />
This could be caused by a known bug when there is a single style in application.resources within app.xaml when not using a startupuri.
The fix is to add an additional style like this...
...
<Style x:Key="unused" />
</Application.Resources>
for more details check out this link.... http://bengribaudo.com/blog/2010/08/19/106/bug-single-application-resources-entry-ignored
There is a sort-of fix for this, but I’ve only been able to make it work at the window level (not the application level).
In order to include a WPF 4.0 resource from a separate project, the resource must be added as a resource in the window’s code behind. The statement belongs in the window’s constructor, prior to the InitializeComponent method call:
public ControlsWindow()
{
this.Resources = Application.LoadComponent(new Uri("[WPF 4.0 ResourceProjectName];Component/[Directory and File Name within project]", UriKind.Relative)) as ResourceDictionary;
InitializeComponent();
}
Note: Replace the '[WPF 4.0 ResourceProjectName]' text with your resource's project name. Also, the '[Directory and File Name within project]' needs to be replaced with the relative location of the resource file (like 'Themes/StandardTheme.xaml')
I go into more details about this issue here.