WPF Resource File used at Resource Dictionary - wpf

to make my Application localizable I use a method from this blog:
http://www.rhyous.com/2010/10/20/using-resources-resx-for-strings-in-a-wpf-application-a-technique-to-prepare-for-localization/
So i have controls defined like this to get the strings from the Resource file :
<Label Content="{x:Static p:Resources.btn_tooltip_edit}"/>
This works fine.
To make my control styles reusable I pack them into an extra Resource Dictionary File.
The Problem is when i want to access the Resource File (.resx) from the Resource Dictionary (.xaml) its not possible and a XAMl Parse Exception (System.Windows.Markup.StaticExtension) is thrown.
<Setter Property="ToolTip" Value="{x:Static p:Resources.btn_tooltip_edit}"/>
Whats wrong?
Is it possible to access the Resource Files from a Style File?

Change the access modifier of Resource File from internal to public.

Related

How to correctly reference external xaml styles in a WPF application?

I believe my question is fairly simple and yet I am having difficulty implementing it successfully. I simply wish to extract the styling of elements in my WPF application because the xaml is rather crowded and xaml is often duplicated.
I therefore wish to place the styling in an external xaml file, in the form of a resource dictionary, then reference that file in the resources section of my code.
I have the following .xaml file:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="PTextBox" TargetType="TextBox" x:Name="PTextBox">
<Setter Property="Foreground" Value="#FFA1C8E7"/>
<Setter Property="BorderBrush" Value="#FFA1C8E7"/>
</Style>
And I reference the dictionary here:
<UserControl.Resources>
<ResourceDictionary x:Key="PegasusStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Resources/Styles/PegasusStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Visual studio has resolved the file location so I know this reference is correct.
The text box the styles are applied to then references the style:
<TextBox Style="{StaticResource PTextBox}"/>
If left as a static resource I get a xaml parse error like so:
An unhandled exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
And if I make the resource dynamic then the styles simply do not get applied at runtime.
I'm not sure if xaml files require certain properties before run time but mine are as follows:
If someone could answer this mystery it would be wonderful. I googled till my fingers bled but none of the answers posted by others have resolved my issues and this seems very rudimentary.
EDIT: Solved. Switching the build action to Page instead of resource has fixed my issue as suggested by Andrew Stephens. This had been hidden by another underlying problem, which is that I had added a boolean to visibility converter (common tool) to my resources. This alone is fine but once I had declared a resource dictionary this converter needed to be brought inside the dictionary as well.
It sounds like a XAML syntax error somewhere, but can also be caused by an unhandled exception in the main window code-behind (if you have any code in here). There are a few ways to debug this cryptic exception here (read the comments for more tips)
Also the Build Action of your .xaml resource file should be "Page" rather than "Resource".
Try building the solution with your newly merged dictionary before you start referencing the external styles in your xaml.
It may seem counter intuitive but it is possible for visual studio to know about a type in another xaml file without the designer being aware which can cause bugs like this.
Koda

No lazy loading for Resource Dictionaries

is there a possibility in WPF / XAML to eager load resource dictionaries? I have a resource dictionary defined in my XAML:
<s:SurfaceWindow.Resources>
<local:SomeConverter x:Key="SomeConverter"/>
<local:SomeView x:Key="SomeView" />
</s:SurfaceWindow.Resources>
I need these resources before the loaded event occurs - is there any way to do that?
Thanks
If you place you ResourceDictionaries BEFORE you create the control then you should be fine. If you are REALLY eager then put your Resources in the App.xaml file

Design templates in a class library at top scope

I use a class library (WPF user control library) to host some user controls which other (C#-) applications in the project solution consume. I want these controls to use XAML ControlTemplates residing at the top scope of the class library. The ControlTemplates do not have to be consumed outside the class library.
Here a template declaration:
<ControlTemplate TargetType="{x:Type Button}" x:Key="TemplateImageButtonSmall">
<Grid>
<Image Name="img" Source="/PSCommonUI;component/Images/Buttons/ButtonMinus_normal.png"/>
</Grid>
</ControlTemplate>
Then I have a user control in the class library, containing:
<Button Height="57" Margin="10,0,6,5" Name="button3" Template="{StaticResource TemplateImageButtonSmall}" Width="82">
In an application, I can use the App.xaml file for defining the templates. However, in a class library I don't have this option.
I have searched the web and found some answers including the use of a generic.xaml file, ComponentResourceKey, merging resource files and other stuff I find exaggeratedly complicated.
Also I read that theme definitions (resources in general) shouldn't reside in a class library.
But if I need some themes ONLY in this class library for the there hosted controls, how is best practice then?
Thanks in advance,
Julian
I am not sure what you meant, however, if you want child UIElements from a specific UIElement and below to use control templates, then you can define the templates in a resource dictionary and merge the dictionary into the top control that you want the dictionary to be visible to.
Edit:
The assembly just contains the classes and resources within it. It has no events of its own (e.g. OnApplicationLoaded).
A control's XAML can contain resources of its own (e.g. control templates) for consumption by itself and child controls and thus define default styling.
Your application can merge the resource dictionaries into any level of the tree (application, window, control, ...) and thus override defaults.
If you want the styling to be dynamic (overrable by importing resource dictionaries) then using the DynamicResource keyword your XAML. If your resource is defined in the same XAML and can not be overridden then use the StaticResource keyword.
Add a resource dictionary to your class library and define your resources (templates) there. It doesn't have to be generic.xaml.
Then in each user control or other .xaml file reference the resource dictionaries you require using Xaml similar to:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="... path to dictionary 1"/>
<ResourceDictionary Source="... path to dictionary 2"/>
<ResourceDictionary Source="... etc"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
You can then use resource keys from the merged dictionaries.

Images bound to images added to resx files using XAML

My WPF application includes a resource file MyResources.resx, containing several strings and images. Because the application will need to be localized, all my references to globalized resources must be made via named properties of the auto-generated MyResources class. The following code works well for string resources:
<Button Content="{x:Static local:Properties.MyResources.ButtonText}" />
However the same does not work for images. Assuming I have an image eflag.bmp added to the resources as a resource named Flag, I would like to be able to do something like this:
<Image Source="{x:Static local:Properties.MyResources.Flag}" />
Please note that the following alternative approach:
<Image Source="/MyNamespace;component/Resources/eflag.bmp" />
cannot be used in this case because it will not be able to handle localization. The problem can be solved using code behind but I am looking for a XAML based solution.
Turn your x:Static into a Binding.Source and add a Converter which does Bitmap to ImageSource.
Source="{Binding Source={x:Static local:Properties.MyResources.Flag},
Converter={StaticResource BitmapToImageSourceConverter}}"
Alternatively you can make the converter a custom markup extension which takes a Bitmap and returns the ImageSource in ProvideValue.
Source="{me:BitmapToImageSource {x:Static local:Properties.MyResources.Flag}}"

WPF: Accessing resources in a control assembly

I have a control for which i want to declare resources in a xaml file. if this was a user control i could put the resources in an <UserControl.Resources> block and reference them in the code via this.Resources["myResourceKey"] how do i achieve the same functionality in a control. at the moment the only link to xaml i have is through the controls static constructor, to reference the style (and control template)
static SlimlineSimpleFieldTextBlock() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(SlimlineSimpleFieldTextBlock), new FrameworkPropertyMetadata(typeof(SlimlineSimpleFieldTextBlock)));
}
but even if i add a block to the xaml <Style.Resources> I dont seem able to reference them (as the Style is null at the OnApplyTemplate stage) and even if i did it would mean if someone eles overrode the style i would lose my resources.
Construct your resource key using ComponentResourceKey. Normal resource keys are searched for only up the visual tree and in your application resources. But any resource key that is a ComponentResourceKey is also searched for in the theme dictionary for the assembly containing the type. (This is also true for Type objects used as resource keys.)
In your Themes/Generic.xaml of the assembly containing a control called "Sandwich" you might have:
<SolidColorBrush x:Key="{ComponentResourceKey local:Sandwich, Lettuce}"
Color="#00FF00" />
<ControlTemplate x:Key="{ComponentResourceKey local:Sandwich, PeanutButter}" ...>
...
</ControlTemplate>
You can reference these resources in code like this:
var lettuce = (Brush)FindResource(
new ComponentResourceKey(typeof(Sandwich), "Lettuce"));
var penutButter = (ControlTemplate)FindResource(
new ComponentResourceKey(typeof(Sandwich), "PeanutButter"));
You can also refer to these resources in XAML like this:
<Border Background="{StaticResource ResourceKey={ComponentResourceKey local:Sandwich, Lettuce}}" />
Both of these forms of reference work from anywhere that FindResource can be used, which is inside the code or XAML for any object derived from FrameworkElement, FrameworkContentElement or Application.
Additional notes
The search algorithm for a ComponentResourceKey resource involves only the assembly contaning the specified type, not the type itself. Thus a control of type Soup could use a ComponentResourceKey of {ComponentResourceKey local:Sandwich,Seasonings} if the Soup and Sandwich classes were in the same assembly. As long as everything about the ComponentResourceKey matches exactly and the resource is actually in the same assembly as the given type, the resource will be found.
Also note that although it is possible to use pack URI to load a ResourceDictionary from another assembly, it is a bad idea to do so. Unlike the Themes/Generic.xaml solution you actually have to modify the application using your controls, and it also suffers from multiple-inclusion and overridability problems.
Whenever you are using Themes/Generic.xaml you must have your ThemeInfoAttribute set correctly on that assembly. You can start with this in your control library's AssemblyInfo.cs:
[assembly:ThemeInfoAttribute(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]

Resources