2017-07-31 42 views
1

我想button_click事件来改变我的项目的语言,所以我用的ResourceDictionary做这样的:如何在MVVM中使用资源字典在运行时更改UI语言?

XAML

<Button Content="{DynamicResource LanguageSetting}" Click="btn_LanguageSetting_Click"/> 

代码隐藏

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; 
    } 

该作品对xaml文件很好,但我也想在后面的代码中更改我的viewmodel的语言。

我ItemsControl的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> 

哪绑定到视图模型这样的:

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(); 
     } 
    } 
} 

而且

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", 
       } 
      }; 
    } 

所以,我怎么想改变郎Uage我的模型SelectableViewModel Code,Name,Description而不是使用这个硬编码?谢谢!

回答

1

我会为您在运行时更改语言提出解决方案。

  1. 创建资源管理器:

    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"); 
    
         } 
        } 
    
  2. 定义资源文件为每种语言类型,只要你想。 enter image description here 上面我已经定义了默认的英文和德文的第二个文件(你可以看到“.de”的扩展名,所以你可以使用其他语言) 确保你打开了Resources.resx属性并选择如定制工具的值PublicResXFileCodeGenerator这一步是必要的,以便通过一个对象提供者,以暴露资源 enter image description here

  3. 经由App.xaml中一个对象提供者注册的资源提供者: enter image description here

  4. 用途:在XAML :

    文本= “{结合ResourcesText1,源= {StaticResource的资源}}”

来自*的.cs:Resources.ResourcesText1

P.S. 当您更改文化时,请确保您拨打SetCulture方法从CultureResouces

+0

感谢您的回答。但是,当我打电话SetCulture()它给了我'错误:'资源'资源未找到'我错过了什么? – BarryLib

+0

您是否定义了资源文件? Resources.resx和Resources.de.resx? –

+0

我应该如何通过这种方式获得当前文化并根据当前价值设定新文化? – BarryLib