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