Tuesday, January 19, 2016

Add resources from Resources.resx to XAML

You may have tried this technique gleaned from the Internet in order to change your WPF GUI's text at runtime according to the language.
When you write the next snippet in your Window's XAML for adding resources from the Resources.resx file and rebuild and run in Visual Studio 2015,

<Window
    ...
    xmlns:props="clr-namespace:MyProject.Properties" 
    >
    <Window.Resources>
        <props:Resources x:Key="LocalResources" />
    </Window.Resources>
    <Window.BindingGroup>
        <BindingGroup Name="localization"/>
    </Window.BindingGroup>
    <Window.Title>
        <Binding Path="WindowTitleStringName"
                 Source="{StaticResource LocalResources}"
                 BindingGroupName="localization"/>
    </Window.Title>
    <Label Content="{Binding LabelContentStringName,
                             Source={StaticResource LocalResources},
                             BindingGroupName=localization}"
        ...
       />
</Window>
// Change to the default Resources.resx in MyWindow.cs
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture ;
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture ;
BindingGroup.BindingExpressions
    .Where( be => be.BindingGroup.Name=="localization" )
    .ToList().ForEach( be => be.UpdateTarget() );

the next exception is thrown.

System.Windows.Markup.XamlParseException / System.MissingMethodException :
    No matching constructor found on type MyProject.Properties.Resources.
    You can use the Arguments or FactoryMethod directives to construct this type.

If you slightly modify Resources.Designer.cs like adding meaningless spaces and just build(not rebuild) and run, the exception is not thrown any more.

Even so, this can be a problem when this app is built in an automated build system.

In order to solve this problem, derive your own Resources class from MyProject.Properties.Resources  and use it with the already defined "local" namespace in your xaml like the next.
namespace MyProject
{
    public class Resources 
        : Properties.Resources
    {
        public Resources()
        {
        }

    }  // End Of Class
}

<Window
    ...
    xmlns:props="clr-namespace:MyProject.Properties"
    >
    <Window.Resources>
         <local:Resources x:Key="LocalResources" />
    </Window.Resources>
    ...
</Window>

1 comment:

  1. If you are involved in localization projects, maybe it can help trying an online service like https://poeditor.com

    ReplyDelete