WPF:如何在运行时更改CurrentUICulture

时间:2011-01-07 14:43:58

标签: c# .net wpf vb.net

我正在尝试更改我的WPF应用在单击事件中使用的语言,但它不会更改。

private void menuItemGerman_Click(object sender, RoutedEventArgs e)
{
   Settings.Default.Culture = "de-DE";

   Thread.CurrentThread.CurrentCulture = new CultureInfo(Settings.Default.Culture);
   Thread.CurrentThread.CurrentUICulture = new CultureInfo(Settings.Default.Culture);
}

我错过了什么?

3 个答案:

答案 0 :(得分:7)

  

我错过了什么?

您更改了在线程中注册的文化,String.Format现在将使用它,但您需要重新加载WPF层次结构中的所有本地化项目。

WPF Localization – On-the-fly Language Selection有更多信息。

答案 1 :(得分:0)

如果您有资源文件,例如:

  • Resources.resx
  • Resources.hu-hu.resx

...,并希望在运行时更改本地化,

...并且不想弄乱其他资源词典并重新编码所有UI本地化,

它将与

一起使用
Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);

但是,它不会更改已经显示的窗口的语言。

要实现这一点,需要更多的编码-必须管理应用程序的生命周期,而不是默认的生命周期。

首先,从App.xaml中删除StartupUri:

<Application
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         x:Class="ADUI.App"
         xmlns:System="clr-namespace:System;assembly=mscorlib" >
     <!--StartupUri="wndMain.xaml">-->
<Application.Resources>
</Application.Resources>

第二,实现一个类,该类现在负责应用程序的生命周期:

public class LocApp: Application
{
    [STAThread]
    public static void Main()
    {
        App app = new App();
        app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
        wndMain wnd = new wndMain();
        wnd.Closed += Wnd_Closed;
        app.Run(wnd);
    }

    private static void Wnd_Closed(object sender, EventArgs e)
    {
        wndMain wnd = sender as wndMain;
        if (!string.IsNullOrEmpty(wnd.LangSwitch))
        {
            string lang = wnd.LangSwitch;

            wnd.Closed -= Wnd_Closed;

            Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);

            wnd = new wndMain();
            wnd.Closed += Wnd_Closed;
            wnd.Show();
        }
        else
        {
            App.Current.Shutdown();
        }
    }
}

不要忘记,将“项目”属性/“应用程序”页面上的启动对象更改为LocApp!

最后,实现一些代码以切换主窗口代码中的语言:

public partial class wndMain : Window
{
    public string LangSwitch { get; private set; } = null;

    // ... blah, blah, blah

    private void tbEn_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        LangSwitch = "en";
        Close();
    }

    private void tbHu_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        LangSwitch = "hu-hu";
        Close();
    }

    // ... blah, blah, blah

}

请确保提供的本地化代码与resx文件语言代码之一(在此示例中为“ hu-hu”)匹配!

此解决方案将关闭并使用所选语言重新打开主窗口,如果主窗口通过其他方式关闭,则退出。

答案 2 :(得分:0)

我也遇到了这个问题,我的解决方法是:

  • Resources.zh-CN
  • Resources.pt-PT

我创建了一个类,该类将返回带有键和标签的字典:

public class Labels : ObservableObject
{
    public Dictionary<string, string> Items { get; set; }
    public string this[string name]
    {
        get
        {
            return Items.ContainsKey(name) ? Items[name] : "";
        }
    }

    public Labels()
    {
        Items = new Dictionary<string, string>();
    }
}

接下来,再上一个类来获取资源:

public static class LanguageUtils
{
    public static Labels GetLangLables(string label)
    {
        var resources = Resources.ResourceManager.GetResourceSet(new CultureInfo(label), true, true);
        return new Labels
        {
            Items = resources.Cast<DictionaryEntry>().ToDictionary(r => r.Key.ToString(), r => r.Value.ToString())
        };
    }
}

当您需要某种语言时:

LanguageUtils.GetLangLables("pt-PT");

一旦,您将无法提高(RaisePropertyChanged())静态属性,请使用以下方法:

public class LanguageContext
{
    private static LanguageContext _languageContext;
    public static LanguageContext Instance
    {
        get
        {
            if (_languageContext == null)
            {
                _languageContext = new LanguageContext();
            }

            return _languageContext;
        }
    }

    protected LanguageContext()
    {
        CurrentLangLabels = LanguageUtils.GetLangLables("en-US");
     }
     public Labels CurrentLangLabels { get; set; }
}

现在您可以更新语言:

LanguageContext.Instance.CurrentLangLabels = LanguageUtils.GetLangLables(SelectedLanguage.Resource);

这样提高:

public Labels CurrentLangLabels
{
   get { return LanguageContext.Instance.CurrentLangLabels; }
   set { RaisePropertyChanged(); }
}

并使用标签:

CurrentLangLabels.Items[LabelName]