Set resource URI of .xaml component - wpf

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

Related

Accessing external resources with C#

I have a wpf application where I want to hide some of the code complexity by creating resource dictionaries.
I have an external file called "SubFolder\LoginPanel.xaml".
I created it as a resource dictionary, and added the reference to the App.xaml file.
In LoginPanel.xaml I have some custom colors defined, brushes, and two storyboards, sbShowLoginMenu, sbHideLoginMenu.
In my MainWindow.xaml I can reference the defined brushes without any problems. However, I want to access my storyboards as well, but from C# code behind for mouse enter.
If I copy the story boards to the MainWindow.xaml file the storyboard works correctly, if I remove it from MainWindow.xaml it does not see the resource. It only sees the resources defined in the MainWindow.xaml.
My question is how do I get my code to work so that I can access the storyboard items from the resource dictionary?
My guess is that I have to add something to the 'Window' tag such as xmlns:rd="clr-namespace:LoginPanel". I know this is not the right syntax but I could not find any documentation for this type of problem.
EDIT: When I try var sb = FindResource("sbShowLoginMenu"), the debugger returns 'resource not found.'.
Well, finally I was able to craft a search criteria that gives the right answer.
Storyboards in ResourceDictionary
Basically storyboards are stateful objects and cannot be placed in a resource dictionary.

Can I prevent App.g.i.cs to be generated?

According to http://stuff.seans.com/2008/07/11/hello-wpf-world-part-1/, it is generated automatically.
Can I prevent to create it so that I can create my own version ?
In App.g.i.cs contains a function Main() is a standard entry point for an application and it is created automatically. If you want, you can provide your own class that implements Main() Link:
We can write in some other classes like Window1.xaml.cs. Then how the system identifies which Main() should get called. That too simple. Go to project properties, select application tab, then change the start up object to Window1.cs.
Here are the three approaches to add your own implementation of App.xaml:
Approach 1
You can delete the existing App.xaml and App.xaml.cs and add a new class file and maybe call it App.cs. In this you can define the App class and write your own Main method as below.
Approach 2
You will run into issues with Approach 1 if you are adding resources and resource dictionaries to your App.xaml. Since the App.xaml is no longer present you will have to write code in your App.cs itself to manage the resources and the merged dictionaries. However this can be more easily handled by modifying the .csproj file and marking App.xaml as Page instead of ApplicationDefinition.
Approach 3
If you have resources and hence want to have App.xaml, but don't like to tamper with .csproj file, then you can include another class in your project that defines the Main method as below.
Also, you can see this link:
Living Without App.xaml and still being able to use Blend

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.

XAML Resx localization not working as expected

I'm attempting to use a resx file to localize some strings I am using in a XAML file. I've looked around at other documentation on the web, and they all seem to recommend a two part process:
Add a clr-namespace to your window, like this:
xmlns:props="clr-namespace:PJConfiguration.Properties"
Use that namespace to localize your string like this:
Content="{x:Static props:Resources.SharedSettings}"
I've done this, and also made sure that my resource classes are public, but I still get the following error from the XAML in step 2:
Cannot find the type 'Resources'.
Does anyone know what else might be causing this problem? Thanks in advance.
In order to make the Resources visible to XAML, you have to make sure that the code generation mode for the resources is set to public. In VS, you find that setting in a ComboBox near the top of the Resources designer window.
For more information on using .Net resources in XAML, you might want to refer to these blog posts: http://wpfglue.wordpress.com/category/localization/
Check if your .resx file is the default Resources.resx file inside the Properties directory of the Application assembly. If that is, there is no reason XAML couldn't find the public class Resources from the correct namespace under local assembly.
Try to specify the assembly name in Step 2 as recommended in this answer.

Loose xaml referencing versioned assemblies

I have a unique development situation and would like some input from others.
I have a situation where I need to load loose xaml files within a rich client application.
A given loose xaml file may have references to an assembly not currently loaded in memory
so the referenced assembly is loaded before the loading the loose xaml. The loose xaml and tied
assemblies are stored on different backend servers which are downloaded to the client and
loaded dynamically.
The loose xaml and/or assemblies are version specific and unfortunately the application can
not be shutdown between rendering xaml.v1 with assembly.v1 from server A
and xaml.v1 with assembly.v2 on server B.
Both assemblies use the same namespace declaration so "older" assemblies can still
work with "newer" ones for any given loose xaml.
The problem is, I do not get a reference to assembly.v2 if I load xaml.v2 which contains
references to "newer" features in assembly.v2.
I obviously cannot unload assembly.v1 from the app domain and I'm not sure if I can
reference items in xaml that are loaded within a different app domain through marshalling.
Any Ideas other than using different namespace references?
I'm guessing that you are already doing dynamic assembly resolution and loading? If so, then you could try substituting a fake assembly name in place of the real assembly name i n the Xaml - you can then use that in your assembly resolution code to load up and return the right assembly. e.g. if your original source Xaml is:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly"
and you know that Xaml wants v2 of MyAssembly, replace the assembly ref in the Xaml string before parsing it to:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly.v2"
.. then in your assembly resolution / load code, when you see the ".v2" bit on the end you look for and load that assembly instead.
Please let me know if I've misunderstood the question, or you aren't current doing any custom assembly resolution - that would certainly be the key in this situation I think.
Another option (assuming that you are versioning your assemblies properly) is to simply include the assembly version in the ns declaration, like so:
xmlns:ns0="clr-namespace:MyCompany.MyProject.MyNameSpace; Assembly=MyCompany.MyProject, Version=1.0.0.0"
I haven't confirmed if this would work, but I believe that it may. You could use the XmlnsDefinitionAttribute (at assembly level). E.g.
Assembly V1 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v1", "MyCompany.MyProject" )]
Assembly V2 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v2", "MyCompany.MyProject" )]
And then in xaml:
xmlns:myassembly="http://schema.mycompany.com/myproject/v2"

Resources