我正在尝试将DocumentViewer的语言从默认英语更改为德语,但没有成功。

作为WPF的新手,我真的很难做到这一点。

重要: DocumentViewer是在后面的代码中创建的,以响应菜单项的单击,然后将其添加为主窗口的Content

我尝试执行以下操作,但似乎无能为力:

myDocumentViewer.Language = System.Windows.Markup.XmlLanguage.GetLanguage("de-DE");

没有进行任何更改,DocumentViewer保留英语。

谷歌搜索Language属性的正确用法,我发现没有任何用处。

问题:

如何将DocumentViewer(使用代码创建)的语言设置为德语?

最佳答案

您可以尝试完成的任务可以完成,但并不容易。

首先,我要指出您的测试机器需要安装适当的语言资源,以允许DocumentViewer用德语显示工具提示等。实际上,这意味着您需要在计算机上安装德语(德国)语言包。有关详细信息,请参见Language Packs

据我所知,下面是我所知道的:

据我所知,WPF并没有内置的基础架构来动态适应Thread.CurrentThread.CurrentUILanguagexml:lang的更改(等同于 FrameworkElement.Language 属性)。

WPF控件主要利用xml:lang来确定其UI语言(假设相应的UI资源可用),并且如果需要,应用程序开发人员可以将其与Thread.CurrentThread.CurrentUILanguage Hook 。像这样,使用数据绑定(bind)本身并不难做到:

<DocumentViewer Language="{Binding UILanguage, ConverterCulture={x:Static glob:CultureInfo.InvariantCulture}}" />

这仍然并不意味着由此绑定(bind)数据的控件将使其UI语言适应Thread.CurrentThread.CurrentUILanguage的更改。每次需要更改UI语言时,都需要重新创建控件,从可视树中删除旧控件,然后添加新控件。大致来说,代码看起来像这样:
private void ChangeCulture()
{
    string ietfLanguageTag = "de-DE";

    var cultureInfo = CultureInfo.GetCultureInfo(ietfLanguageTag);

    Thread.CurrentThread.CurrentCulture = cultureInfo;
    Thread.CurrentThread.CurrentUICulture = cultureInfo;

    UILanguage = ietfLanguageTag;

    var parent = VisualTreeHelper.GetParent(_documentViewer) as Grid;
    int index = parent.Children.IndexOf(_documentViewer);

    parent.Children.Remove(_documentViewer);
    _documentViewer = new DocumentViewer();
    parent.Children.Add(_documentViewer);
}

上面的代码段假定DocumentViewer的可视父级是Grid,并且由变量_documentViewer支持。

通常,以上解决方案过于简单,不适用于MVVM场景(在WPF应用程序中通常是这种情况)。您可能具有到DocumentViewer实例的数据绑定(bind),并且创建新实例将需要在代码中重新创建那些绑定(bind)(另一方面,如果碰巧不涉及数据绑定(bind),并且所有设置都在代码中设置,则我认为上述方法会奏效)。

您可以通过创建一个简单的用户控件来进一步改善这一点,该控件封装了DocumentViewer以及您可能希望保留的任何有趣的绑定(bind)。您的控件如下所示:

XAML:
<UserControl x:Class="LocalizedDocumentViewer.CultureAwareDocumentViewer"
         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:glob="clr-namespace:System.Globalization;assembly=mscorlib"
         xmlns:local="clr-namespace:LocalizedDocumentViewer"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         d:DesignHeight="300"
         d:DesignWidth="300"
         mc:Ignorable="d">
<Grid>
    <DocumentViewer DataContext="{Binding}" Language="{Binding UILanguage, ConverterCulture={x:Static glob:CultureInfo.InvariantCulture}}" />
</Grid>

XAML.cs
using System.Windows.Controls;

namespace LocalizedDocumentViewer
{
    public partial class CultureAwareDocumentViewer : UserControl
    {
        public CultureAwareDocumentViewer()
        {
            InitializeComponent();
        }
    }
}

现在,您可以轻松地将其包含在主应用程序UI中,如下所示。下面的XAML包括几个其他UI元素(按钮和标签),它们将有助于显示完整的示例:

MainWindow XAML:
<Window x:Class="DocViewerLoc.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:local="clr-namespace:DocViewerLoc"
    xmlns:localizedDocumentViewer="clr-namespace:LocalizedDocumentViewer;assembly=LocalizedDocumentViewer"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    Title="DocumentViewer Culture Change Demo"
    Width="525"
    Height="350"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    mc:Ignorable="d">
<Grid>
    <!--  Row and Column Definitions  -->
    <!--  Define a small row on the top of the window to place buttons  -->
    <Grid.RowDefinitions>
        <RowDefinition Height="25" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="100" />
        <ColumnDefinition Width="1*" />
    </Grid.ColumnDefinitions>


    <!--  Controls  -->

    <Button Grid.Row="0"
            Grid.Column="0"
            Command="{Binding CultureChanger}"
            CommandParameter="{Binding RelativeSource={RelativeSource Self},
                                       Path=Content}">
        en-us
    </Button>
    <Button Grid.Row="0"
            Grid.Column="1"
            Command="{Binding CultureChanger}"
            CommandParameter="{Binding RelativeSource={RelativeSource Self},
                                       Path=Content}">
        de-DE
    </Button>
    <Label Grid.Row="0" Grid.Column="2">&lt;-- Click on one of these buttons to change UI culture</Label>
    <Grid Grid.Row="1" Grid.ColumnSpan="3">
        <localizedDocumentViewer:CultureAwareDocumentViewer x:Name="_documentViewer" DataContext="{Binding}" />
    </Grid>

</Grid>

后面的相应代码具有几个依赖项属性,这些属性用于帮助与上述XAML中的绑定(bind)进行通信。

MainWindow.xaml.cs
using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace DocViewerLoc
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            CultureChanger = new SimpleCommand(ChangeCulture);
            InitializeComponent();
        }

        /// <summary>
        ///  ChangeCulture is called when one of the buttons with caption
        /// 'en-us' or 'de-DE' is pressed.
        /// </summary>
        /// <param name="parameter">
        /// A string containing the caption 'en-us' or 'de-DE'.
        /// </param>
        private void ChangeCulture(object parameter)
        {
            string ietfLanguageTag = parameter as string;
            if (ietfLanguageTag == null) return;

            var cultureInfo = CultureInfo.GetCultureInfo(ietfLanguageTag);

            Thread.CurrentThread.CurrentCulture = cultureInfo;
            Thread.CurrentThread.CurrentUICulture = cultureInfo;

            // This will ensure that CultureAwareDocumentViewer's Language property
            // binds to the updated value set here when it is instantiated next.
            UILanguage = ietfLanguageTag;

            // Remove the old instance of _documentViewer from the UI.
            var parent = VisualTreeHelper.GetParent(_documentViewer) as Grid;
            int index = parent.Children.IndexOf(_documentViewer);
            parent.Children.Remove(_documentViewer);

            // Create a new instance of CultureAwareDocumentViewer. This will
            // use the updated value of UILanguage bind it to its Language (xml:lang)
            // property, thus resulting in the appropriate language resources being
            // loaded.
            _documentViewer = new LocalizedDocumentViewer.CultureAwareDocumentViewer();

            // Now, add the _documentViewer instance back to the UI tree.
            parent.Children.Add(_documentViewer);
        }

        /// <summary>
        /// ICommand used to bind to en-us and de-DE buttons in the UI
        /// </summary>
        #region CultureChange
        public SimpleCommand CultureChanger
        {
            get { return (SimpleCommand)GetValue(CultureChangerProperty); }
            set { SetValue(CultureChangerProperty, value); }
        }

        // Using a DependencyProperty as the backing store for CultureChanger.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CultureChangerProperty =
            DependencyProperty.Register("CultureChanger", typeof(SimpleCommand), typeof(MainWindow), new PropertyMetadata(default(SimpleCommand)));

        #endregion

        /// <summary>
        /// UILanguage property used to bind to the FrameworkElement.Language (xml:lang) property
        /// in the DocumentViewer object within the CultureAwareDocumentViewer control.
        /// </summary>
        #region UILanguage

        public string UILanguage
        {
            get { return (string)GetValue(UILanguageProperty); }
            set { SetValue(UILanguageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for UILanguage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty UILanguageProperty =
            DependencyProperty.Register("UILanguage", typeof(string), typeof(MainWindow), new PropertyMetadata(Thread.CurrentThread.CurrentUICulture.IetfLanguageTag));

        #endregion
    }

    /// <summary>
    /// Simple implementation of the ICommand interface that delegates
    /// Execute() to an Action<object>.
    /// </summary>
    public class SimpleCommand : ICommand
    {
#pragma warning disable 67
        public event EventHandler CanExecuteChanged;
#pragma warning restore 67
        public SimpleCommand(Action<object> handler)
        {
            _handler = handler;
        }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            _handler?.Invoke(parameter);
        }

        private Action<object> _handler;
    }
}

下面的屏幕截图显示了生成的应用程序UI。请注意,DocumentViewer中的资源将在英语和德语之间切换,但是UI的其余部分不会切换(因为我们没有尝试本地化我们的应用程序!)。

DocumentViewer中显示en-us资源的应用程序:

c# - 将DocumentViewer的语言设置为德语(从代码而不是XAML)-LMLPHP

DocumentViewer中显示de-DE资源的应用程序:

c# - 将DocumentViewer的语言设置为德语(从代码而不是XAML)-LMLPHP

09-20 07:36