Reputation: 461
So I made a little test application to test out, if this binding localized text to TextBlock
works. I have my doubts, that it should/could be done better and if yes, then your recommendations would be really nice!
Also I have in XAML code commented out TextBlock
, that does Bind value directly form resx
, but I couldn't get it working.. Any ideas about how I could change that text there would be awesome as well! :)
XAML:
<Window x:Class="LocalizationTestWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:LocalizationTestWpf.Resources"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button x:Name="btnChange" Content="Button" HorizontalAlignment="Left" Margin="206,192,0,0" VerticalAlignment="Top" Width="75" Click="btnChange_Click"/>
<!--<TextBlock x:Name="txtDisplay" HorizontalAlignment="Center" Margin="206,138,236,152" TextWrapping="Wrap" Text="{x:Static local:strings.Hello}" VerticalAlignment="Center" TextAlignment="Center" Width="75" Height="29"/>-->
<TextBlock x:Name="txtDisplay" HorizontalAlignment="Center" Margin="206,138,236,152" TextWrapping="Wrap" Text="{Binding SayHello}" VerticalAlignment="Center" TextAlignment="Center" Width="75" Height="29"/>
</Grid>
</Window>
C#:
// http://social.technet.microsoft.com/wiki/contents/articles/22420.binding-to-resources-resx-files-in-xaml.aspx -- how to bind WPF
int step = 0;
public MainWindow()
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("et-EE");
// Adds my class (object) as datacontext, so I can bind those values.
DataContext = new StringValues();
InitializeComponent();
}
private void btnChange_Click(object sender, RoutedEventArgs e)
{
switch (step)
{
case 0:
// Change language
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
// Update DataContext -- Do I need to do it like that?
DataContext = new StringValues();
InitializeComponent();
btnChange.Content = "Russian";
step++;
break;
// Following steps are same as 'case 0', only different language.
case 1:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU");
DataContext = new StringValues();
btnChange.Content = "English";
step++;
break;
case 2:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
DataContext = new StringValues();
btnChange.Content = "Estonian";
step++;
break;
default:
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("et-EE");
DataContext = new StringValues();
btnChange.Content = "France";
step = 0;
break;
}
}
}
public class StringValues
{
public string SayHello
{
get { return strings.Hello; }
}
}
Project folder:
How WPF looks like in VS (note, that textblock is empty with this binding method):
Sample RESX file:
Upvotes: 1
Views: 3029
Reputation: 8843
A possible approach can be to use ResourceDictionary
s instead of resx files.
XAML:
<Window x:Class="BindToResources.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Button x:Name="btnChange" Content="Button" Click="btnChange_Click"/>
<TextBlock x:Name="txtDisplay" Text="{DynamicResource Hello}" />
</StackPanel>
</Window>
Code behind:
public partial class MainWindow : Window
{
int step = 0;
public MainWindow()
{
InitializeComponent();
var cultureInfo = CultureInfo.GetCultureInfo("et-EE");
Thread.CurrentThread.CurrentUICulture = cultureInfo;
SetLocalization(cultureInfo);
}
private void btnChange_Click(object sender, RoutedEventArgs e)
{
CultureInfo cultureInfo;
switch (step)
{
case 0:
cultureInfo = CultureInfo.GetCultureInfo("fr-FR");
break;
case 1:
cultureInfo = CultureInfo.GetCultureInfo("ru-RU");
break;
case 2:
cultureInfo = CultureInfo.GetCultureInfo("en-US");
break;
default:
cultureInfo = CultureInfo.GetCultureInfo("et-EE");
break;
}
Thread.CurrentThread.CurrentUICulture = cultureInfo;
SetLocalization(cultureInfo);
btnChange.Content = cultureInfo.EnglishName;
step = ++step % 4;
}
private static void SetLocalization(CultureInfo cultureInfo)
{
var dict = new ResourceDictionary
{
Source = new Uri(string.Format("pack://application:,,,/Languages/{0}.xaml", cultureInfo.Name))
};
var existingDict = Application.Current.Resources.MergedDictionaries.FirstOrDefault(
rd => rd.Source.OriginalString.StartsWith("pack://application:,,,/Languages/"));
if (existingDict != null)
{
Application.Current.Resources.MergedDictionaries.Remove(existingDict);
}
Application.Current.Resources.MergedDictionaries.Add(dict);
}
}
You have ResourceDictionary
classes for each language (language_code.xaml format):
You define the localized strings in each dictionary.
Example of Russian:
<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="Hello">Здравствуйте</system:String>
</ResourceDictionary>
Example of Estonian:
<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="Hello">Tere</system:String>
</ResourceDictionary>
So the main idea here is to use DynamicResource
for the lookup as you can see in the first XAML and add the correct ResourceDictionary
to Application.Current.Resources
during runtime.
This is working for me:
Upvotes: 4