Number of Objects Resulting from a Loose xaml File - wpf

Suppose I have a loose xaml file with one resource in it, keyed "MyResource", and that I pull that loose xaml file into two other xaml files via ResourceDictionary.MergedDictionaries. Now suppose I put the following line of code in both of the code-behind files for the two xaml files:
object obj = FindResource("MyResource");
Will both references be to the same object, or will they be to distinct objects?
Thanks,
Dave

The answer depends on how you load the loose XAML file. If you load it once and the same reference is added to two different MergedDictionaries, then by default you'd get the same reference to your "MyResource".
If you load the XAML file twice, you will effectively create two instances of the ResourceDictionary (and thus two instances of your resource).
In a single ResourceDictionary, you can specify if a resource is shared using the x:Shared attribute, which is true by default. Setting this to false, will force new instances to be created for each request of the resource. There are some restrictions on the use of this attribute, which are explained on the MSDN page.

Related

Set resource URI of .xaml component

I have a .xaml UserControl named MyUserControl.xaml and I want to set its resource URI.
Per default, WPF generates a URI that includes a resource name, which is equal to the resource it belongs to such as
"/MyNamespace;component/myusercontrol.xaml"
for the .xaml named MyUserControl.xaml
How can I have a UserControl MyUserControl.xaml and make WPF generate an individual resource identifies such as
"/MyNamespace;component/myusercontrol_A.xaml" or
"/MyNamespace;component/myusercontrol_B.xaml" ?
The reason why I want to do that is described here.
In the image below you can see the resource identifier I am talking about:
and therein:
Note, that that question is the origin of this question and might help to understand its background.
After a week suffering and laboring with this issue, I finally found both the reason for the problem and its solution.
The problem lies within the auto-generated *.g.i.cs file, which is called by the InitializeComponent() method of a UserControl, as seen by the following:
This file generates a string (a Resource Locator) that expresses the path to that xaml-component, as seen by the following:
Now, if you have multiple versions of the same assembly and both versions include the same xaml-file, WPF does not know what xaml-file to instantiate, because the Resource Locator only references the name of the assembly but not its version.
This results in a TargetInvocationException, saying that
{"The component 'MyNamespace.MyUserControl' does not have a resource identified by the URI '/MyAssembly;comoponent/myusercontrol.xaml'"}
as follows:
The simple (but most definitely not obvious) solution for this is to add the version of the assembly to this Resource Locator. This can be achieved by modifying the build-file of the project by adding the <AssemblyVersion>-tag as follows:
Credits for this go to:
this blog
this SO thread

What is the correct way to define images in XAML

Currently I add an image in XAML this way :
Put the file in the project's folder, in a sub-directory named "Resources",
Set its "Build Action" property to "Resource",
Add in my XAML file : <Image Source="/Resources/myImage.png />
And it works great.
But in SO I keep seeing people writing this instead :
<Image Source="pack://application:,,,/MyApplicationNamespace;component/Resources/myImage.jpg" />
Also recently, I've found that in Project Properties -> Resources, you can add files like images, texts...
So which of these 3 possibilities should I use ?
The Image Source="/Resources/myImage.png syntax used in your XAML to refer to an image in a sub folder is actually equivalent to the following syntax pack://application:,,,/Resources/myImage.jpg and this is one of the variations used to access binary resources in XAML.
Since the first two options are the same written differently this leaves us with the third option.
When to use the resource file ?
I usually tend to use them when i have different resources assemblies that are used as satellite assemblies which are in turn used for localization to different cultures. Also they can be used when you want to access those resources and switch them at run-time.

Can the WPF ResourceDictionary return a new instance for each request

We're using ResourceDictionaries to store layout information for our app. The lazy initialisation is great because we can grab the required layout for an element only when that element is created. The problem is that each element gets the same instance from the ResourceDictionary for each one that shares the layout (or the same one if it goes out of scope and is needed later).
We could store templates in the dictionary then it doesn't matter if they're shared but we have quite a nice system going if it wasn't for this caching behaviour.
Is there a way to change this behaviour of the dictionary or am I going to have to write my own class which creates items from the XAML on demand?
Try applying x:Shared="false" attribute. Each resource should then get seperate copy.

XAML Unable to Read Values From Resx file

I have an composite application which has a Shell window and has some modules, each module is loaded on to the shell using MEF (Microsfot Prism). Shell Itself has a resource file default(Resource.resx) and for other languages(like Resource.ar-SA.resx) too to support Localilzation.
For Xaml : I had used x:Static Resource.KeyName
In c# Code : I had used GetString(keyName, culture) to get the required string.
To support Localization, I have added a line of code which gets the current culture of the system and loads the required Resx File.
For Setting the Current Culture.
Resource.Culture =
new System.Globalization.CultureInfo(System.Globalization.CultureInfo.CurrentCulture.Name);
in App.Xaml.cs
All these work Completely fine.
Similarly, each module which is loaded using MEF has Resource files as mentioned above. But in case of Modules, resource Key defined in the Xaml for a specific language file is not working. Its always getting the values from the Default (Resource.Resx) file. But any key used in the code using ResourceManager class works fine.
I ended up keeping all my resources in an "Infrastructure" project so all the resources are loaded from one place, it just made it simpler.
My xaml bindings look like this
Get the refrence to your resx class.
xmlns:resources="clr-namespace:Infrastructure.resources;assembly=Infrastructure"
now get the text
Content="{x:Static resources:Resources.Activity_Regarding}"
You might be doing this already but I cant see. You would want to make sure the namespace matches for the resx you want to use. So your modules namespace.

Wpf: Passing Parameters To A ResourceDictionary

Is there a way to pass parameters to a resource dictionary? I think that I can attach a code behind for the purpose of specifying event handlers, but unfortunately, I also need to access a reference to the parent control from the event handlers. The codebehind, I believe, can be attached by specifying an x:Class attribute for the resource dictionary in xaml, and then creating a class in the same folder, the filename for which is something like [resource dictionary name].xaml.cs.
The purpose is to seperate the code for four hierarchical data templates that I'm using in a single treeview control. The xaml for the treeview is getting a bit long and ugly to look at, so I was hoping to break it down into four resource dictionaries. Any thoughts are welcome!
Andrew
You know you can merge your Resource Dictionaries and then reference the DataTemplate within those dictionaries as needed within the TreeView.
Resource dictionaries sound like a slightly peculiar way to do this. Resource dictionaries are all about sharing instances - they let you use a single instance of something (e.g. a style, a template, a brush, or whatever) from multiple places. They're not really a mechanism for dividing your UI up to simplify individual Xaml files.
The usual mechanism for splitting overly complicated Xaml files up into a few, more manageable smaller files is the user control. (Resource dictionary merging comes into play when you already have a resource dictionary, and it's got too big. But you wouldn't normally introduce a resource dictionary just to start splitting things up. On the contrary, resource dictionaries tend to encourage overly large Xaml files, which is why dictionary merging had to be invented in the first place!)
Most of the time, when I define a data template, I make it contain nothing but a single user control. And if that becomes more complex, I'd split that user control up into more user controls.
From your description, it sounds like your Xaml file has become large because you've got four large hierarchical data templates in there. If you took the body of each template and turned it into a user control, your four templates would now become very simple - something like this:
<HierarchicalDataTemplate x:Key="t1" ItemsSource="{Binding Path=Children}">
<loc:TreeItemTypeOne />
</HierarchicalDataTemplate>
and you'd most likely no longer need to put those templates into separate files. But because the guts of each template is now in a user control, that gives you a place to put your codebehind.
You mention needing a reference to the parent control. That worries me - it makes it sound like you have too much code in your codebehind. But one thing at a time... You could solve that problem by defining a dependency property called ParentControl on your user control, and then put this in the template:
<loc:TreeItemTypeOne
ParentControl="{Binding RelativeSource=
{RelativeSource AncestorType=loc:ParentControlType}}" />
But frankly, as soon as I find myself in a position where I need this, I ask myself: how did I get myself into a position where that seemed necessary, and what can I do to fix that?

Resources