简体   繁体   English

C#WPF将本地化文本绑定到元素

[英]C# WPF binding localized text to element

So I made a little test application to test out, if this binding localized text to TextBlock works. 所以我做了一个小测试应用程序来测试,如果这个绑定本地化文本到TextBlock工作。 I have my doubts, that it should/could be done better and if yes, then your recommendations would be really nice! 我怀疑,它应该/可以做得更好,如果是的话,那么你的建议真的很棒!

Also I have in XAML code commented out TextBlock , that does Bind value directly form resx , but I couldn't get it working.. Any ideas about how I could change that text there would be awesome as well! 另外我在XAML代码中注释掉了TextBlock ,它确实将Bind值直接形成resx ,但是我无法让它工作..关于我如何能够改变那些文本的任何想法都会很棒! :) :)

XAML: 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#: 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; }
        }
    }

Project folder: 项目文件夹:

项目目录

How WPF looks like in VS (note, that textblock is empty with this binding method): WPF在VS中的样子(请注意,使用此绑定方法该文本块为空):

MainWindows.xaml

Sample RESX file: 样本RESX文件:

.resx文件

A possible approach can be to use ResourceDictionary s instead of resx files. 一种可能的方法是使用ResourceDictionary而不是resx文件。

XAML: 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>

Code behind: 代码背后:

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);
    }
}

You have ResourceDictionary classes for each language (language_code.xaml format): 您有每种语言的ResourceDictionary类(language_code.xaml格式):

Solution Explorer

You define the localized strings in each dictionary. 您可以在每个字典中定义本地化字符串。

Example of Russian: 俄语的例子:

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

Example of Estonian: 爱沙尼亚语的例子:

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

So the main idea here is to use DynamicResource for the lookup as you can see in the first XAML and add the correct ResourceDictionary to Application.Current.Resources during runtime. 因此,这里的主要思想是使用DynamicResource进行查找,如第一个XAML中所示,并在运行时将正确的ResourceDictionary添加到Application.Current.Resources

This is working for me: 这对我有用:

最终结果

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

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