WPF:如何在运行时更改CurrentUICulture

z4bn682m  于 2022-11-18  发布在  其他
关注(0)|答案(4)|浏览(203)

我尝试更改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);
}

我错过了什么?

ryoqjall

ryoqjall1#

我错过了什么?
您更改了向线程注册的区域性和字符串。Format现在将使用此区域性,但您需要重新加载WPF层次结构中的所有本地化项。
WPF Localization – On-the-fly Language Selection提供了更多信息。

zte4gxcn

zte4gxcn2#

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

  • 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”)!
此解决方案将关闭并重新打开主窗口(使用所选语言),如果主窗口以其他方式关闭,则将退出。

z31licg0

z31licg03#

我也遇到过这个问题,我的解决方案是:

  • Resources.en-US
  • 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]
cqoc49vn

cqoc49vn4#

这对某些人来说可能会派上用场。我已经使用了上面乔治& Chris Schaller给出的建议,使这个在我的项目中工作,而不需要创建新的应用程序类。

public string LangSwitch { get; private set; } = null;    
private void BtnLngPl_Click(object sender, RoutedEventArgs e)
        {
            CultureInfo current = CultureInfo.CurrentUICulture;
            CultureInfo newUiCulture;
            if (current.Name.Equals("en-US"))
            {
                newUiCulture = new CultureInfo("pl");
                Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                if (System.Windows.Application.Current.MainWindow != null)
                    ((MainWindow)System.Windows.Application.Current.MainWindow).Closed += Wnd_Closed;
                Thread.CurrentThread.CurrentCulture = newUiCulture;
                Thread.CurrentThread.CurrentUICulture = newUiCulture;
                LangSwitch = "pl";
                Close();
            }
            else
                newUiCulture = new CultureInfo("en-US");

            CultureInfo.CurrentUICulture = newUiCulture;
            Console.WriteLine(@"The current UI culture is now {0}",
                CultureInfo.CurrentUICulture.Name);
        }

其他必要的代码可以从乔治的答案中获取。不确定这是一个多好的解决方案,但对我来说很好。

相关问题