SilverLight Control Library - Cannot Reference Relative MergedDictionary by Generic.xaml - c#

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

Related

Generic xaml file isn't getting added to Resources in UWP Class Library

So I have a seemingly simple setup but for some reason my UWP app isn't processing my Generic.xaml file
I have a shared class library that targets 16299 and its min version is 16299.
I created a Themes directory and under it I put a Generic.xaml file which is a Resource dictionary.
Inside this I tried adding a style and then referencing it by key but the UWP app isn't able to find the style.
For example
Generic.xaml
<Style TargetType="ListViewItem" x:Key="ListViewItemEvenRowStyle" >
<Setter Property="Padding" Value="0" />
<Setter Property="Background" Value="Black" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
<Style TargetType="ListViewItem" x:Key="ListViewItemOddRowStyle" >
<Setter Property="Padding" Value="0" />
<Setter Property="Background" Value="White" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
Which results in this exception when I reference it with StaticResource
Windows.UI.Xaml.Markup.XamlParseException: 'The text associated with
this error code could not be found.
Cannot find a Resource with the Name/Key ListViewItemEvenRowStyle
I also tried putting this in ResourceDictionary.ThemeResources and referencing it with ThemeResource but I keep getting the same result.
This is the CSProj definition
<Page Include="Themes\Generic.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
You need to use ResourceDictionary.MergedDictionaries, instead of ResourceDictionary.ThemeResources.
In your main UWP project, open the 'App.xaml' file, add the following code:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="YourClassLibrary/Themes/Generic.xaml"></ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
More information, please see XAML theme resources and ResourceDictionary.MergedDictionaries.
[Updated on 2019/7/10]
I'm curious how Infragistics, Telerik, and Microsoft UWP.Toolkit manage to accomplish this. If I add a telerik control dll to my project and reference their controls, I don't need to add anything to my resource dictionaries.
The Telerik and WindowsCommunityToolkit are open source. You could check their source code. These controls are custom controls. Each control has its own style file and it will be applied to it in the control's constructor method by setting DefaultStyleKey = typeof(YourCustomControlClass).
For example, the Microsoft.Toolkit.Uwp.UI.Controls/Carousel/ control. You could see the Carousel.xaml style file is in the same folder with the Carousel.cs class. In the Carousel constructor, it uses DefaultStyleKey = typeof(Carousel); to apply the style. But just with these steps, the system still cannot find the corresponding style. You could see the Microsoft.Toolkit.Uwp.UI.Controls/Themes/ folder, it has a Generic.xaml file in there. It actually is a 'ResourceDictionary'. It use ResourceDictionary.MergedDictionaries to merge resource in different custom control folders.
With this way, the main project just need to add reference to your control library and use the controls directly without using ResourceDictionary.MergedDictionaries in the main project.

Is it possible to override one part of a control template in a Telerik WPF theme?

I am using the Telerik Windows 8 theme in my WPF application.  However, I do not like the way the checkbox checked state is indicated using a colored square rather than an actual checkmark as in the Windows 7 theme.  It was very simple to copy the checkbox template and modify it to use the checkbox checkmark from the Windows 7 theme checkbox template.
However, I am having trouble finding a way to add the style that contains this modified template to my Application.Resources in such a way as to apply it to all checkboxes in my application.  For some reason, the template in the Telerik Windows 8 theme continues to be the one that is applied.
I have tried a few different approaches, yet nothing seems to work.  My latest approach is to add the following style to my Application.Resources resource dictionary:
<Style BasedOn="{StaticResource {telerik:ThemeResourceKey ThemeType=telerik:Windows8Theme, ElementType=CheckBox}}" TargetType="CheckBox" >
    <Setter Property="Template">
    ....
    </Setter>
</Style>
Does anyone know the answer to this question? Is what I am trying to do possible?
Thanks,
Craig
Make sure you are ferencing the DLLs from the NoXaml folder of your Telerik install
Don't add any reference to any of the Theme DLLs
In your Telerik WPF install location, go into Themes.Implicit > WPF40 > Windows8 > Themes
Put the .xaml files from there into your solution
Reference them in your App.xaml resource dictionary:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Themes/Office2016/System.Windows.xaml" />
<ResourceDictionary Source="Themes/Office2016/Telerik.Windows.Controls.xaml" />
<ResourceDictionary Source="Themes/Office2016/Telerik.Windows.Controls.GridView.xaml" />
etc...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
Now you can go into the System.Windows.xaml file, and find the style for the checkbox and edit the style to change the square to a tick
(I think it's the Rectangle called CheckVisual in the Checkbox Template which you need to change)

Unable to override default style of wpf control in generic.xaml

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.

XAML designer cannot resolve references using custom implementation of ResourceDictionary

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?

WPF not applying default styles defined in MergedDictionaries?

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.

Categories

Resources