Reputation: 299
I want to change my project language by button_click event, so I use ResourceDictionary to do it like this:
XAML
<Button Content="{DynamicResource LanguageSetting}" Click="btn_LanguageSetting_Click"/>
Code Behind
public static string windowCurrentLanguageFile = "Language/en.xaml";
private void btn_LanguageSetting_Click(object sender, RoutedEventArgs e)
{
windowCurrentLanguageFile = windowCurrentLanguageFile == "Language/en.xaml"
? "Language/fr.xaml"
: "Language/en.xaml";
var rd = new ResourceDictionary() { Source = new Uri(windowCurrentLanguageFile, UriKind.RelativeOrAbsolute) };
if (this.Resources.MergedDictionaries.Count == 0)
this.Resources.MergedDictionaries.Add(rd);
else
this.Resources.MergedDictionaries[0] = rd;
}
This works fine for the xaml file, but I also want to change my viewmodel's language in the code behind.
My ItemsControl in the xaml:
<ItemsControl ItemsSource="{Binding ItemOperate}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewmodel:SelectableViewModel}">
<Border x:Name="Border" Padding="0,8,0,8" BorderThickness="0 0 0 1" BorderBrush="{DynamicResource MaterialDesignDivider}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Checkerz" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<ToggleButton VerticalAlignment="Center" IsChecked="{Binding IsSelected}"
Style="{StaticResource MaterialDesignActionLightToggleButton}"
Content="{Binding Code}" />
<StackPanel Margin="8 0 0 0" Grid.Column="7">
<TextBlock FontWeight="Bold" Text="{Binding Name}" />
<TextBlock Text="{Binding Description}" />
</StackPanel>
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter TargetName="Border" Property="Background" Value="{DynamicResource MaterialDesignSelection}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Which Binding to the ViewModel like this:
public class SelectableViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
if (_isSelected == value) return;
_isSelected = value;
OnPropertyChanged();
}
}
private char _code;
public char Code
{
get { return _code; }
set
{
if (_code == value) return;
_code = value;
OnPropertyChanged();
}
}
private string _name;
public string Name
{
get { return _name; }
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged();
}
}
private string _description;
public string Description
{
get { return _description; }
set
{
if (_description == value) return;
_description = value;
OnPropertyChanged();
}
}
}
And
public MainViewModel()
{
_itemOperate = CreateData();
}
private static ObservableCollection<SelectableViewModel> CreateData()
{
return new ObservableCollection<SelectableViewModel>
{
new SelectableViewModel
{
Code = 'E',
Name = "Erase",
Description = "Erase The MCU Chip By Page"
},
new SelectableViewModel
{
Code = 'D',
Name = "Detect",
Description = "Detect The MCU Flash",
},
new SelectableViewModel
{
Code = 'P',
Name = "Programming",
Description = "Programming The MCU Chip By Hex File",
},
new SelectableViewModel
{
Code = 'V',
Name = "Verify",
Description = "Verify The Downing Code",
},
new SelectableViewModel
{
Code ='L',
Name = "Lock",
Description = "Lock The Code To Protect The MCU",
}
};
}
So how I suppose to change the language my model SelectableViewModel Code
, Name
, Description
instead of using this hard code? Thanks!
Upvotes: 2
Views: 2379
Reputation: 1935
I will propose you a solution for changing the language at runtime.
Create the resource manager:
public class CultureResources
{
private static bool isAvailableCulture;
private static readonly List<CultureInfo> SupportedCultures = new List<CultureInfo>();
private static ObjectDataProvider provider;
public CultureResources()
{
GetAvailableCultures();
}
/// <summary>
/// Gets automatically all supported cultures resource files.
/// </summary>
public void GetAvailableCultures()
{
if (!isAvailableCulture)
{
var appStartupPath = AppDomain.CurrentDomain.BaseDirectory;
foreach (string dir in Directory.GetDirectories(appStartupPath))
{
try
{
DirectoryInfo dirinfo = new DirectoryInfo(dir);
var culture = CultureInfo.GetCultureInfo(dirinfo.Name);
SupportedCultures.Add(culture);
}
catch (ArgumentException)
{
}
}
isAvailableCulture = true;
}
}
/// <summary>
/// Retrieves the current resources based on the current culture info
/// </summary>
/// <returns></returns>
public Resources GetResourceInstance()
{
return new Resources();
}
/// <summary>
/// Gets the ObjectDataProvider wrapped with the current culture resource, to update all localized UIElements by calling ObjectDataProvider.Refresh()
/// </summary>
public static ObjectDataProvider ResourceProvider
{
get {
return provider ??
(provider = (ObjectDataProvider)System.Windows.Application.Current.FindResource("Resources"));
}
}
/// <summary>
/// Changes the culture
/// </summary>
/// <param name="culture"></param>
public void ChangeCulture(CultureInfo culture)
{
if (SupportedCultures.Contains(culture))
{
Resources.Culture = culture;
ResourceProvider.Refresh();
}
else
{
var ci = new CultureInfo("en");
Resources.Culture = ci;
ResourceProvider.Refresh();
}
}
/// <summary>
/// Sets english as default language
/// </summary>
public void SetDefaultCulture()
{
CultureInfo ci = new CultureInfo("en");
Resources.Culture = ci;
ResourceProvider.Refresh();
}
/// <summary>
/// Returns localized resource specified by the key
/// </summary>
/// <param name="key">The key in the resources</param>
/// <returns></returns>
public static string GetValue(string key)
{
if (key == null) throw new ArgumentNullException();
return Resources.ResourceManager.GetString(key, Resources.Culture);
}
/// <summary>
/// Sets the new culture
/// </summary>
/// <param name="cultureInfo"> new CultureInfo("de-DE"); new CultureInfo("en-gb");</param>
public void SetCulture(CultureInfo cultureInfo)
{
//get language short format - {de} {en}
var ci = new CultureInfo(cultureInfo.Name.Substring(0,2));
ChangeCulture(ci);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
// CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-GB");
}
}
Define resource file for each language type as you want.
above I've defined the default for English and the second file for German (you can see the ".de" extension. So you do for any other language.
Be sure that you open the Resources.resx properties and select as Custom Tool the value PublicResXFileCodeGenerator. This step is necessary in order to expose the Resource through an object provider.
Register the Resource provider via an object provider in the App.xaml:
Usage: in Xaml :
Text="{Binding ResourcesText1, Source={StaticResource Resources}}"
From *.cs : Resources.ResourcesText1.
P.S. When you change the culture be sure you call SetCulture method from the CultureResouces.
Upvotes: 3