【问题标题】:C# WPF binding localized text to elementC# WPF 将本地化文本绑定到元素
【发布时间】:2016-01-19 16:55:47
【问题描述】:

所以我做了一个小测试应用程序来测试,如果这个绑定本地化文本到TextBlock 有效。我怀疑它应该/可以做得更好,如果是,那么您的建议会非常好!

另外,我在 XAML 代码中注释掉了 TextBlock,它确实直接从 resx 绑定值,但我无法让它工作.. 关于如何更改该文本的任何想法也会很棒! :)

XAML:

<Window x:Class="LocalizationTestWpf.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:LocalizationTestWpf.Resources"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">


    <Grid>
        <Button x:Name="btnChange" Content="Button" HorizontalAlignment="Left" Margin="206,192,0,0" VerticalAlignment="Top" Width="75" Click="btnChange_Click"/>
        <!--<TextBlock x:Name="txtDisplay" HorizontalAlignment="Center" Margin="206,138,236,152" TextWrapping="Wrap" Text="{x:Static local:strings.Hello}" VerticalAlignment="Center" TextAlignment="Center" Width="75" Height="29"/>-->
        <TextBlock x:Name="txtDisplay" HorizontalAlignment="Center" Margin="206,138,236,152" TextWrapping="Wrap" Text="{Binding SayHello}" VerticalAlignment="Center" TextAlignment="Center" Width="75" Height="29"/>

    </Grid>
</Window>

C#:

// http://social.technet.microsoft.com/wiki/contents/articles/22420.binding-to-resources-resx-files-in-xaml.aspx    -- how to bind WPF

        int step = 0;

        public MainWindow()
        {
            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("et-EE");
            // Adds my class (object) as datacontext, so I can bind those values.
            DataContext = new StringValues();
            InitializeComponent();
        }

        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            switch (step)
            {
                case 0:
                    // Change language
                    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("fr-FR");
                    // Update DataContext -- Do I need to do it like that?
                    DataContext = new StringValues();
                    InitializeComponent();

                    btnChange.Content = "Russian";
                    step++;
                    break;
                // Following steps are same as 'case 0', only different language.
                case 1:
                    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("ru-RU");
                    DataContext = new StringValues();
                    btnChange.Content = "English";
                    step++;
                    break;
                case 2:
                    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-US");
                    DataContext = new StringValues();
                    btnChange.Content = "Estonian";
                    step++;
                    break;
                default:
                    Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("et-EE");
                    DataContext = new StringValues();
                    btnChange.Content = "France";
                    step = 0;
                    break;
            }
        }


    }

    public class StringValues
    {
        public string SayHello
        {
            get { return strings.Hello; }
        }
    }

项目文件夹:

WPF 在 VS 中的样子(注意,使用这种绑定方法,文本块是空的):

示例 RESX 文件:

【问题讨论】:

    标签: c# wpf xaml localization resx


    【解决方案1】:

    一种可能的方法是使用ResourceDictionarys 而不是 resx 文件。

    XAML:

    <Window x:Class="BindToResources.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"
            mc:Ignorable="d"
            Title="MainWindow" Height="350" Width="525">
        <StackPanel>
            <Button x:Name="btnChange" Content="Button" Click="btnChange_Click"/>
            <TextBlock x:Name="txtDisplay" Text="{DynamicResource Hello}" />
        </StackPanel>
    </Window>
    

    后面的代码:

    public partial class MainWindow : Window
    {
        int step = 0;
    
        public MainWindow()
        {
            InitializeComponent();
    
            var cultureInfo = CultureInfo.GetCultureInfo("et-EE");
            Thread.CurrentThread.CurrentUICulture = cultureInfo;
            SetLocalization(cultureInfo);
        }
    
        private void btnChange_Click(object sender, RoutedEventArgs e)
        {
            CultureInfo cultureInfo;
    
            switch (step)
            {
                case 0:
                    cultureInfo = CultureInfo.GetCultureInfo("fr-FR");
                    break;
                case 1:
                    cultureInfo = CultureInfo.GetCultureInfo("ru-RU");
                    break;
                case 2:
                    cultureInfo = CultureInfo.GetCultureInfo("en-US");
                    break;
                default:
                    cultureInfo = CultureInfo.GetCultureInfo("et-EE");
                    break;
            }
    
            Thread.CurrentThread.CurrentUICulture = cultureInfo;
            SetLocalization(cultureInfo);
            btnChange.Content = cultureInfo.EnglishName;
            step = ++step % 4;
        }
    
        private static void SetLocalization(CultureInfo cultureInfo)
        {
            var dict = new ResourceDictionary
            {
                Source = new Uri(string.Format("pack://application:,,,/Languages/{0}.xaml", cultureInfo.Name))
            };
    
            var existingDict = Application.Current.Resources.MergedDictionaries.FirstOrDefault(
                rd => rd.Source.OriginalString.StartsWith("pack://application:,,,/Languages/"));
    
            if (existingDict != null)
            {
                Application.Current.Resources.MergedDictionaries.Remove(existingDict);
            }
    
            Application.Current.Resources.MergedDictionaries.Add(dict);
        }
    }
    

    每种语言都有ResourceDictionary 类(language_code.xaml 格式):

    您在每个字典中定义本地化字符串。

    俄语示例:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:system="clr-namespace:System;assembly=mscorlib">
        <system:String x:Key="Hello">Здравствуйте</system:String>
    </ResourceDictionary>
    

    爱沙尼亚语示例:

    <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                        xmlns:system="clr-namespace:System;assembly=mscorlib">
        <system:String x:Key="Hello">Tere</system:String>
    </ResourceDictionary>
    

    所以这里的主要思想是使用DynamicResource 进行查找,如您在第一个 XAML 中所见,并在运行时将正确的ResourceDictionary 添加到Application.Current.Resources

    这对我有用:

    【讨论】:

    • 我也让它工作了。但是这种方法在MainWindow.xaml 页面中给出了错误Text="{DynamicResource Hello}"(“资源“Hello”无法解析”)。为什么会出现这个错误,有没有办法解决它?
    • 我的错,不是错误,是警告。
    猜你喜欢
    • 1970-01-01
    • 2011-07-17
    • 2015-12-30
    • 2011-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-12
    • 2020-04-25
    相关资源
    最近更新 更多