Inheritance in ResourceDictionary (XAML) - c#

In WPF, would it be possible for a ResourceDictionary (Child.xaml) to inherit from another ResourceDictionary (Base.xaml) using only XAML notation.
I tried using the tag ResourceDictionary and then try to see if some kind of merge or basedOn was available, but I couldn't find anything.
For example, I have the following (assume) child ResourceDictionary (Child.xaml file):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:core="clr-namespace:System;assembly=mscorlib">
</ResourceDictionary>
Is it possible from there derive from another base ResourceDictionary using basedOn or something like that?

Related

The good practice for defining a reusable resources in WPF

I've been writing a CAD-style program in .Net, for this I have to have a lot of Brushes and Custom DashStyles.
So far I have defined them in a static class. for example:
public static readonly Brush GridBrushInModel = Brushes.DarkGray;
Now I can use the brush whenever I want. I have also Freezed them though.
My question is, is this the way this should be done? Or there are better ways? For example defining in ResourceDictionary? How it is done?
Shared resources in a WPF application are typically stored as a ResourceDictionary. Each dictionary should have its own XAML file (if you wish to split up your resources).
They are pretty easy to define:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="MyCoolBrush" Color="Black"/>
</ResourceDictionary>
Note that I gave the element a x:Key attribute. This is what you use to reference the resource later.
Finally, you have to merge the dictionary into the using code. This can be done at any level, though its most commonly done in the Window.Resources or in App.xaml.
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/MyBrushes.xaml"/>
</ResourceDictionary.MergedDictionaries>
...
</ResourceDictionary>
</Window.Resources>
Once you have them, you can reference them in XAML like this:
<Grid Background={StaticResource MyCoolBrush}/>

DynamicResource with DataTemplate

I have UserControl which needs to perform some multi-linguality. In constructor, I dynamically load proper XAML with ResourceDictionary. In that XAML I have:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Key="somekey">Some Label</system:String></ResourceDictionary>
I then have
Header = {DynamicResource somekey}
in DataGridTextColumn in DataTemplate which is also used by this UserControl. It looks like the DataTemplate doesn't know about the new ResourceDictionary.
But, it does not work. Please, why?
I guess you should bind the (re)source to the header content. The resource itself cannot notify any change, so the binding may be the solution.
Header={Binding Source={DynamicResource someKey}, Path=.}
Anyway I'm not sure: never try such a condition.

VS2010 designer not working when the ResourceDictionary is in a subfolder

I have a project which contains the entry point of my application and a ResourceDictionary. In a first time, these files were located at the root of the project. At this time, I could see all the components (button for exemple) modified by the style in the designer of xaml files in other projects.
Now, I have subfolders like this : src/launcher which contains my entry point and src/styles which contains my ResourceDictionary. But now, the components are not styled in the designer of VS2010. The program compiles and works well, but the designer doesn't work. I get the "Cannot find the resource ..." error constantly.
The code of my main xaml file is :
<Application x:Class="MANAGER.Program"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
<Application.Resources>
<ResourceDictionary Source="../Styles/Style.xaml"></ResourceDictionary>
</Application.Resources>
</Application>
Why the designer doesn't work ?
Your code should look this way in order to use subdirectories out of your application root directory:
<Application x:Class="MANAGER.Program"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="Application_Startup">
<Application.Resources>
<ResourceDictionary Source="pack://siteoforigin:,,,../Styles/Style.xaml"></ResourceDictionary>
</Application.Resources>
</Application>
It might have something to do with the format of the "Source" attribute.
The format needs to be a Pack URI like "pack://siteoforigin:,,,/SiteOfOriginFile.xaml"
Have a look at these documentations in MSDN:
ResourceDictionary.Source Property
Packet URIs in WPF

In WPF how do I reference a static resource that is defined in a different XAML file?

In WPF how do I reference a static resource that is defined in a different XAML file? It's in the same project.
The other XAML file will need to be a resource dictionary. You merge it into the current file using the MergedDictionaries property of the current ResourceDictionary. See Merged Resource Dictionaries on MSDN. Their example:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="myresourcedictionary.xaml"/>
<ResourceDictionary Source="myresourcedictionary2.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
Then within that Page object you can reference static resources defined in myresourcedictionary.xaml or in myresourcedictionary2.xaml.
"different XAML file" could mean a few different things:
App.xaml: Resources are automatically included in the resource tree of anything that's opened so you don't need to do anything extra.
Window or Page .xaml: Resources can be accessed by any child of an instance of the object like a UserControl that is used in a Window.
ResourceDictionary: Needs to be explicitly merged into the resource tree somewhere above where it is used. This can be App.xaml, Windowxx.xaml, or some lower level element. Use ResourceDictionary.MergedDictionaries to do this.
There are also lots of alternate ways to specify the path but this is the simplest:
<Window>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/MyResourceDict.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>

Accessing ResourceDictionary from WPF UserControl

I'm trying to access a resource dictionary in a UserControl code-behind via C# and I'm having little success.
Merged Dictionary:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/BiometricDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Embedded Dictionary:
<UserControl.Resources>
<BitmapImage x:Key="imageDefault">/Resources/Images/default_thumb.png</BitmapImage>
<BitmapImage x:Key="imageDisconnected">/Resources/Images/disconnect_thumb.png</BitmapImage>
<BitmapImage x:Key="imageFailed">/Resources/Images/failed_thumb.png</BitmapImage>
<BitmapImage x:Key="imageSuccess">/Resources/Images/success_thumb.png</BitmapImage>
</UserControl.Resources>
Code behind:
var resourceDictionary = new ResourceDictionary();
resourceDictionary.Source = new Uri("/Resources/BiometricDictionary.xaml", UriKind.Relative);
I've tried all of the examples and helpful tips but coming up short. Right now, success would be the ability to load the dictionary. Any suggestions?
To access one of your UserControl's XAML resources in your codebehind, all you need to do is access the Resources property of the UserControl. Something like this:
BitmapImage myImage = (BitmapImage)this.Resources["imageDefault"];
Though, the preferred method is to use FindResource(), which will search the entire logical tree for a match to the key, rather than just the object it is called on.
BitmapImage myImage = (BitmapImage)this.FindResource("imageDefault");
Try to remove the forward slash infront of your location. The only time you should use /Resources is if you have to go up a library first. like ../Resources
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/BiometricDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
Hope this helps you.
So, you have a ResourceDictionary defined in a UserControl's assembly, and would like to access it from that UserControl's code-behind?
You should be able to. However, if the code you listed is in the constructor, you may not have access to the resource dictionary (might not be loaded yet). Try adding that same code to your UserControl's "loaded" event, and see if that works. If you're simply trying to access a resource, such as a style or template, using the "FindResource" or "TryFindResource" functions directly from your class should work as well (i.e. you don't need to have an object of type "ResourceDictionary").
Hope that helps!
d'Oh...after compiling to the local bin so that references are relative, I implemented the pack URI solution found here: ResourceDictionary in a separate assembly and then FindResource(x:key value here).
#PeterAllenWeb, #Pwninstein, thanks for your quick responses and getting me thinking again.

Categories