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

时间:2016-01-19 16:55:47

标签: c# wpf xaml localization resx

所以我做了一个小测试应用程序来测试,如果这个绑定本地化文本到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; }
        }
    }

项目文件夹:

Project directory

WPF中WPF的外观(注意,使用此绑定方法,该文本块为空):

MainWindows.xaml

示例RESX文件:

.resx file

1 个答案:

答案 0 :(得分:2)

一种可能的方法是使用ResourceDictionary而不是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格式):

Solution Explorer

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

俄罗斯的例子:

<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

这对我有用:

End result