繁体   English   中英

在WPF中本地化命令和CultureInfo

[英]Localizing Commands and CultureInfo in WPF

当前,我正在尝试创建支持在运行时进行语言切换的应用程序。 我找到了一个教程,建议为此使用Resource Dictionaries 对于XAML中具有其内容集的元素,建议的方法效果很好,例如,如下所示: <Button Content="{DynamicResource MainTitle}"

事实是,我的MenuItem (已将其Header设置为绑定到其的Command Text不会根据CurrentUICulture更改Header 尽管我正在通过语言切换来更改一种语言,但它仍然是相同的,或者应该说是针对项目的默认语言而正确的。 代表支持的语言的MenuItems

这是我正在使用的代码。

App.xaml.cs

public partial class App : Application
{
    private static String prefix = "Resources/lang.";
    public static event EventHandler LanguageChanged;
    private static List<CultureInfo> m_Languages = new List<CultureInfo>();
    public static List<CultureInfo> Languages
    {
        get
        {
            return m_Languages;
        }
    }
    public static CultureInfo Language
    {
        get
        {
            return System.Threading.Thread.CurrentThread.CurrentUICulture;
        }
        set
        {
            if (value == null) throw new ArgumentNullException("value");
            if (value == System.Threading.Thread.CurrentThread.CurrentUICulture) return;

            System.Threading.Thread.CurrentThread.CurrentUICulture = value;
            ResourceDictionary dictionary = new ResourceDictionary();
            dictionary.Source = new Uri(String.Format(prefix+ "{0}.xaml", value.Name), UriKind.Relative);
            ResourceDictionary oldDictionary = (from d in Current.Resources.MergedDictionaries
                                                where d.Source != null &&
                                                d.Source.OriginalString.StartsWith(prefix)
                                                select d).First();

            if (oldDictionary != null)
            {
                int index = Current.Resources.MergedDictionaries.IndexOf(oldDictionary);
                Current.Resources.MergedDictionaries.Remove(oldDictionary);
                Current.Resources.MergedDictionaries.Insert(index, dictionary);
            }
            else
            {
                Current.Resources.MergedDictionaries.Add(dictionary);
            }
            LanguageChanged(Current, new EventArgs());
        }
    } 
    public App()
    {
        InitializeComponent();
        App.LanguageChanged += App_LanguageChanged;
        m_Languages.Clear();
        m_Languages.Add(new CultureInfo("en"));
        m_Languages.Add(new CultureInfo("ru-RU"));
        Language = WpfTestProject.Properties.Settings.Default.DefaultLanguage;
    }
    public void App_LanguageChanged(Object sender, EventArgs e)
    {
        WpfTestProject.Properties.Settings.Default.DefaultLanguage = Language;
        WpfTestProject.Properties.Settings.Default.Save();
    }
}

MainWindow.xaml.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        App.LanguageChanged += LanguageChanged;
        SetLanguageMenu();
    }

    private void SetLanguageMenu()
    {
        CultureInfo currLang = App.Language;
        LangMenu.Items.Clear();
        foreach (var lang in App.Languages)
        {
            MenuItem menuLang = new MenuItem();
            Debug.WriteLine("Here is a display name: " + lang.DisplayName);
            menuLang.Header = lang.DisplayName;
            menuLang.Tag = lang;
            menuLang.IsChecked = lang.Equals(currLang);
            menuLang.Click += ChangeLanguageClick;
            LangMenu.Items.Add(menuLang);
        }
    }
    private void LanguageChanged(Object sender, EventArgs e)
    {
        //I've tried resseting LanguageMenu from here - no effect
        CultureInfo currLang = App.Language;
        foreach (MenuItem i in LangMenu.Items)
        {
            CultureInfo ci = i.Tag as CultureInfo;
            i.IsChecked = ci != null && ci.Equals(currLang);
        }
    }
    private void ChangeLanguageClick(Object sender, EventArgs e)
    {
        MenuItem mi = sender as MenuItem;
        if (mi != null)
        {
            CultureInfo lang = mi.Tag as CultureInfo;
            if (lang != null)
            {
                App.Language = lang;
                SetLanguageMenu();
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfTestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfTestProject"
    mc:Ignorable="d"
    Title="{DynamicResource MainTitle}" Height="600" Width="800">
<Window.CommandBindings>
    <CommandBinding Command="ApplicationCommands.New" Executed="NewCommand_Executed"/>
    <CommandBinding Command="ApplicationCommands.Open" Executed="OpenCommand_Executed"/>
    <CommandBinding Command="ApplicationCommands.Save" Executed="SaveCommand_Executed"/>
    <CommandBinding Command="ApplicationCommands.SaveAs" Executed="SaveAsCommand_Executed"/>
</Window.CommandBindings>
<Window.InputBindings>
    <KeyBinding Key="N" Modifiers="Ctrl" Command="{Binding ApplicationCommands.New}"/>
    <KeyBinding Key="O" Modifiers="Ctrl" Command="{Binding ApplicationCommands.Open}"/>
    <KeyBinding Key="S" Modifiers="Ctrl" Command="{Binding ApplicationCommands.Save}"/>
    <KeyBinding Key="S" Modifiers="Ctrl+Shift" Command="{Binding ApplicationCommands.SaveAs}"/>
</Window.InputBindings>
    <DockPanel Name="DockPanel" HorizontalAlignment="Stretch" LastChildFill="False" VerticalAlignment="Stretch">
        <MenuItem Command="ApplicationCommands.Open" Header="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Command.Text}"/>
        <MenuItem Name="LangMenu" Header="Languages" HorizontalAlignment="Right"/>
    </DockPanel>
</Window>

更新

英文资源词典

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:WpfTestProject.Properties"
                xmlns:v="clr-namespace:System;assembly=mscorlib">
<v:String x:Key="MainTitle">Title</v:String>

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
    <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
        <section name="WpfTestProject.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
    </sectionGroup>
</configSections>
<startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<userSettings>
    <WpfTestProject.Properties.Settings>
        <setting name="DefaultLanguage" serializeAs="String">
            <value>en</value>
        </setting>
    </WpfTestProject.Properties.Settings>
</userSettings>

关于我在做什么错的任何想法?

事实是,我的MenuItem(已将其Header设置为绑定到其的Command Text)不会根据CurrentUICulture更改Header。

当然不是,为什么呢?

您应该以与设置其他元素的本地化文本相同的方式设置MenuItemHeader

<MenuItem Command="ApplicationCommands.Open" Header="{DynamicResource OpenText}"/>

显然,您必须这样做才能使本地化也能跨MenuItem元素进行。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM