XAML Resx localization not working as expected - wpf

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.

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

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.

Cannot see named Silverlight control in code

In my first few hours with Silverlight 3, as an avid WPF user, I am greatly disappointed at the many things it doesn't support. This seems like an odd issue to me and it's so generic that I cannot find anything online about it.
I have the following XAML:
<controls:TabControl x:Name="workspacesTabControl" Grid.Row="1"
Background="AntiqueWhite" ItemsSource="{Binding Workspaces, ElementName=_root}"/>
However, I cannot see the workspacesTabControl in code-behind. I thought maybe IntelliSense is just being mean and tried to go ahead and compile it anyway, but got an error:
Error 1 The name 'workspacesTabControl' does not exist in the current context
How do I access controls in code-behind?
EDIT: I realized I've pasted the wrong error - I have two controls inside the UserControl called workspacesTabControl and menuStrip. I cannot get to either one of them by their name in the code-behind.
Just in case, here is the XAML for the menuStrip:
<controls:TreeView Grid.ColumnSpan="2" Height="100" x:Name="menuStrip"
ItemContainerStyle="{StaticResource MenuStripStyle}"
ItemsSource="{Binding Menu, ElementName=_root}"/>
EDIT AGAIN:
I'm not sure if this is helpful, but I've taken a look at the InitializeComponent() code and here's what I saw:
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
public void InitializeComponent() {
if (_contentLoaded) {
return;
}
_contentLoaded = true;
System.Windows.Application.LoadComponent(this, new System.Uri("/SapphireApplication;component/SapphireMain.xaml", System.UriKind.Relative));
}
It seems that it simply loads the XAML when it runs (not before or during compilation) so the menuStrip and workspacesTabControl names don't actually get registered anywhere (as they usually are in WPF/win Forms). Could that attribute be a problem? And where do I get rid of this requirement for all the future UserControls I make?
Check the properties in VS for the xaml file itself... make sure the Build Action is set to Page.
As ridiculous as it may sound, I have resorted to using FindName() method to access named items in code-behind:
this.FindName("workspacesTabControl") as TabControl
I realize that this is a ridiculous way but I am forced to use this for now. Please let me know if someone else has encountered this problem and have come up with a better solution!
When you first create a control, Visual Studio does not pick it up with intellisense. However, after you try to build the project, it should become availble. You can also just type the name in without intellisense and then build it. Haven't verified this, but I heard this was on the list of things to fix in SL4.
That being said, if you name a control inside of a datatemplate, that control is not directly accessible in code-behind. This is the same for WPF, though.
You should be able to see it in the codebehind, that part works the same as WPF, maybe if you fix the problem with the menuStrip, then visual studio will be able to build the xaml paty of the page and ull be able to access the tabcontrol
I've seen the same problem in my Silverlight development. Specific to my problem my named controls were nested inside other controls (i.e. a datagrid) and I was unable to access them in my code behind. Any named controls at the same nesting level or above the previously mentioned datagrid worked fine but anything inside it was lost into the abyss.
As already mentioned, it should just appear in Intellisense, however the fact that you're getting an error related to something else, i.e. "menuStrip" is probably interfering with Intellisense. Resolve that error and you'l probably find that you can access the "workspacesTabControl" control.
Are you possibly using some sample code or something where they've named a control "menuStrip" and you've renamed it?
Good luck
Check that you don't have any controls using the same class name as a namespace name. For example:
namespace Solution.ProjectName.workspacesTabControl
{
public class workspacesTabControl
{
...
}
}
This will also give you this error.
Good luck,
Mark

Is it possible to find out the assembly and file containing a DependencyObject?

I am currently working on a little localization framework for WPF (don't even think about pointing me to locBAML...) and wondered if it was possible to find out the containing assembly of a specified DependencyObject.
For example: I have a normal window definition in XAML in the file Window1.xaml. The window contains a StackPanel and inside it a TextBlock resides.
Is it possible to find out which assembly contains the Window1.xaml file when only having a reference to the TextBlock?
Is it also possible to find out the file name of the xaml file ("Window1.xaml" in this case)?
Thanks in advance and best regards,
3Fox
I think something like this would work.
Window window = Window.GetWindow(YourTextBox);
Assembly assembly = Assembly.GetAssembly(window.GetType());

WPF - Shut-off autogen of Main in App.g.cs

I'm learning WPF.
I want to provide my own Main method in my App.xaml.cs rather than getting one generated for me in App.g.cs. However I keep getting conflicts because I haven't found out how to stop an additional Main from being generated.
Is there a setting in my project file or elsewhere that controls this?
I found the answer here. http://learnwpf.com/post/2007/12/13/How-can-I-provide-my-own-Main%28%29-method-in-my-WPF-application.aspx
It is:
The way WPF knows to create the Main() method for a particular xaml file is through the build action property set for App.xaml - it has a build action of ApplicationDefinition. By changing this to Page WPF won't create the Main method and you can provide your own in a regular class file you add to the project.
However in the comments to the above blog, a comment notes there may be issues with blend and it references: http://blogs.msdn.com/expression/archive/2008/04/09/creating-a-wpf-blend-project-that-loads-resources-in-code.aspx . I don't fully understand the issues yet.
You can also just create a separate class (for example, Entry) which is responsible for bootstrapping your application. Then go to project settings and set your startup object to Entry. That way you don't even have to disable the autogenerated method.
The easiest way is to set the Build Action in the Properties window from ApplicationDefinition to Page for App.Xaml.
Then you can define your own entry point.
I found a solution:
Copy the data from your app.xaml file
Delete app.xaml file and re-create with the same name
Create `main` method in .cs file, and paste your old copied code into it
One way is to forgo defining an Application-derived class in XAML, so you can manually define the Main method with your custom requirement
The Easy way just create a class like Startup.cs with build action to compile
and remove ApplicationDefinition from App.xaml convert that to page
and remove it from any other file in the application

Resources