如何在运行时使用资源字典更改 UI 语言? [英] How to change UI language using resource dictionary at run time?

查看:41
本文介绍了如何在运行时使用资源字典更改 UI 语言?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 button_click 事件更改我的项目语言,所以我使用 ResourceDictionary 这样做:

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"/>

背后的代码

    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 文件,但我还想在后面的代码中更改视图模型的语言.

This works fine for the xaml file, but I also want to change my viewmodel's language in the code behind.

我在 xaml 中的 ItemsControl:

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

像这样绑定到 ViewModel:

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

那么我想如何更改我的模型 SelectableViewModel CodeNameDescription 的语言而不是使用这个硬代码?谢谢!

So how I suppose to change the language my model SelectableViewModel Code, Name, Description instead of using this hard code? Thanks!

推荐答案

我会为您提出一个在运行时更改语言的解决方案.

I will propose you a solution for changing the language at runtime.

  1. 创建资源管理器:

  1. 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");

        }
    }

  • 根据需要为每种语言类型定义资源文件.上面我定义了英语的默认值和德语的第二个文件(你可以看到.de"扩展名.所以你可以为任何其他语言做.确保您打开 Resources.resx 属性并选择值 PublicResXFileCodeGenerator 作为自定义工具.为了通过对象提供程序公开资源,此步骤是必要的.

  • 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.

    通过 App.xaml 中的对象提供程序注册资源提供程序:

    Register the Resource provider via an object provider in the App.xaml:

    用法:在 Xaml 中:

    Usage: in Xaml :

    Text="{Binding ResourcesText1, Source={StaticResource Resources}}"

    来自 *.cs:Resources.ResourcesText1.

    附言当您更改文化时,请务必从 CultureResouces 中调用 SetCulture 方法.

    P.S. When you change the culture be sure you call SetCulture method from the CultureResouces.

    这篇关于如何在运行时使用资源字典更改 UI 语言?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆