If you’ve done globally-focused development on Windows Phone, you already know that to change the display language, you have to do so in the Settings area of the phone, then reboot the emulator (or physical device) for the change to take effect.
What a pain. Wouldn’t it be better to change the UI language on-demand? Not to mention provide end users the ability to do so within your app as an added convenience. In this blog post, I’ll show you just how to make that happen.
If you haven’t already, check out my blog post on localizing your app – this is obviously the first step. Get some resource strings in other languages defined for the elements of your application.
Now that you’ve got your app all wired up with some added languages, if even machine generated, let’s get to making it on-the-fly switchable.
Let’s have a look at some tweaks to the default phone project created for Windows Phone 8.0 (and 8.1 Silverlight):
First, take a look at LocalizedStrings
. This is the class that your text elements are (hopefully) already binging to in order to pull the resource from your RESX file.
Tweak it as follows:
1: public class LocalizedStrings : INotifyPropertyChanged
2: {
3: private static AppResources _localizedResources = new AppResources();
4:
5: public AppResources LocalizedResources { get { return _localizedResources; } }
6:
7: internal void ChangeCulture(string cultureName)
8: {
9: AppResources.Culture = new System.Globalization.CultureInfo(cultureName);
10:
11: OnPropertyChanged("LocalizedResources");
12: }
13:
14: public event PropertyChangedEventHandler PropertyChanged;
15: void OnPropertyChanged([CallerMemberName]string propertyName = "")
16: {
17: if (this.PropertyChanged != null)
18: {
19: PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
20: }
21: }
22: }
That is, make it inherit from INotifyPropertyChanged
, add the ChangeCulture
and OnPropertyChanged
methods.
The trick we’re exploiting here is the binding to LocalizedStrings
that’s being done in your XAML when you create a localized app. It’s XAML. So when it creates a binding, it wires up PropertyChanged
if the source object supports it. So we’re making LocalizedStrings
support it. We’ll utilize this in a minute.
Now have a look at your XAML. Something like this I imagine:
1: <TextBlock HorizontalAlignment="Left"
2: TextWrapping="Wrap"
3: Text="{Binding Source={StaticResource LocalizedStrings},
Path=LocalizedResources.testString, Mode=OneWay}"
4: VerticalAlignment="Top"
5: Margin="22,10,0,0" />
Since Path
is hitting the LocalizedResources
property of the LocalizedStrings
object, this is all we need to fire a PropertyChanged
event for when we want the string
s to update!
So, in my app, I’ve got an INotifyPropertyChanged
ViewModel
that reacts to a CurrentCulture
string
property when it’s set as follows:
1: private string _currentLanguage;
2: public string CurrentLanguage
3: {
4: get
5: {
6: return _currentLanguage;
7: }
8: set
9: {
10: if (_currentLanguage != value)
11: {
12: _currentLanguage = value;
13: OnPropertyChanged();
14:
15: ChangeUICulture(_currentLanguage);
16: }
17: }
18: }
So yeah, it updates the property’s value, but then calls another method. Let’s take a look at that dude:
1: private void ChangeUICulture(string currentLanguage)
2: {
3: ((LocalizedStrings)App.Current.Resources["LocalizedStrings"]).ChangeCulture(currentLanguage);
4: }
And boom. We get the LocalizedStrings
instance out of our App’s Resources (put there automatically as part of the project template) and call our new ChangeCulture
method on it. If you don’t have your localized string
s class in your app resources, just add this to App.xaml:
1: <Application.Resources>
2: <local:LocalizedStrings xmlns:local="clr-namespace:PhoneApp1" x:Key="LocalizedStrings"/>
3: </Application.Resources>
Now watch as the magic cascades string
change events to all bound controls when you call our new method on LocalizedStrings
!