如何将 cultureinfo(语言)属性 应用于 WPF richtextbox 选择

How to apply cultureinfo (language) property to WPF richtextbox selection

我通常可以在网络上的某个地方找到解决方案,主要是在 SO 上。我已经尝试了两天来解决这个问题,所有尝试都产生了完全相同的结果。希望这里有人可以提供我需要的帮助。

我没有在应用程序的任何地方添加任何语言代码,除了在组合框中,用户可以在组合框中 select 语言和下拉事件,当他们 select 下面看到的语言遵循以下定义时实时出价。

下面是 richtextbox

的 xaml 定义
            <RichTextBox Name="rtbDoc" IsDocumentEnabled="true" Padding="4"
                     MinHeight="350" HorizontalAlignment="Stretch"
                     VerticalAlignment="Stretch" SpellCheck.IsEnabled="True" VerticalScrollBarVisibility="Auto"
                     HorizontalScrollBarVisibility="Auto" AcceptsTab="True" IsTabStop="False"  
                     IsVisibleChanged="rtbDoc_IsVisibleChanged" 
                     KeyUp="rtbDoc_KeyUp" PreviewMouseUp="rtbDoc_MouseUp" PreviewMouseDown="rtbDoc_PreviewMouseDown"
                     PreviewKeyDown="rtbDocPreviewKeyDown"
                     ContextMenuOpening="rtb_ContextMenuOpening" 
                     ToolTip="Edit documents" Width="941"  >

下面是应该应用语言的事件中的代码,但仅更改拼写检查器,不仅针对 selected 文本,而且针对整个文档。

               private void cbbLanguage_DropDownClosed(object sender, EventArgs e)
    {
        if (this.cbbLanguage.SelectedIndex < 0) { return; }

        int iLcid = (int)this.cbbLanguage.SelectedValue;
        _ci = new System.Globalization.CultureInfo(iLcid);

        // following does not seem to have any desire affect
        //System.Threading.Thread.CurrentThread.CurrentCulture = _ci;
        //System.Threading.Thread.CurrentThread.CurrentUICulture = _ci;
        //CultureInfo ci2 = CultureInfo.CreateSpecificCulture(_ci.Name);

        // both of following changes only spellchecker for document so that all English text underlined
        //InputLanguageManager.SetInputLanguage(this.rtbDoc, CultureInfo.CreateSpecificCulture(ci2.Name));
        //XmlLanguage xl = this.rtbDoc.Document.Language;

        int iIdx = this.cbbLanguage.SelectedIndex;
        DataRowView drv = this.cbbLanguage.SelectedItem as DataRowView;
        DataRow[] dr = _dtLanguages.Select("LanguageId = " + drv[0].ToString());  // number id of language selected

        XmlLanguage xl2 = XmlLanguage.GetLanguage(dr[0]["LanguageName"].ToString());

        // this works in changing the property and all words in document 
        //  become underlined indicating spellchecker changed but text remained English
        //this.rtbDoc.Language = xl2;  

        if (this.rtbDoc.Selection.Text.Length > 1)
        {
            // this works to immediately (no focus change necessary) to 
            //   change the property and the spellchecker shows the entire 
            //   doc content misspelled, but the selected text remains english
            this.rtbDoc.Selection.ApplyPropertyValue(FrameworkElement.LanguageProperty, xl2);  
        }

    }

您可以处理 rtbDoc 中的 GotFocusLostFocus 事件并更改 InputLanguageManager

<RichTextBox Name="rtbDoc" IsDocumentEnabled="true" Padding="4"
                 GotFocus="ChangeLanguage"
                 LostFocus="ChangeToDefault"
                 MinHeight="350" HorizontalAlignment="Stretch"
                 VerticalAlignment="Stretch" SpellCheck.IsEnabled="True" VerticalScrollBarVisibility="Auto"
                 HorizontalScrollBarVisibility="Auto" AcceptsTab="True" IsTabStop="False"  
                 IsVisibleChanged="rtbDoc_IsVisibleChanged" 
                 KeyUp="rtbDoc_KeyUp" PreviewMouseUp="rtbDoc_MouseUp" PreviewMouseDown="rtbDoc_PreviewMouseDown"
                 PreviewKeyDown="rtbDocPreviewKeyDown"
                 ContextMenuOpening="rtb_ContextMenuOpening" 
                 ToolTip="Edit documents" Width="941"  >

在代码中

public CultureInfo defaultLanguage;
public CultureInfo ci;
private void cbbLanguage_DropDownClosed(object sender, EventArgs e)
{

    int iLcid = Int32.Parse(_lstLanguages[this.cbbLanguage.SelectedIndex].LanguageId);
    ci = new System.Globalization.CultureInfo(iLcid);
    System.Threading.Thread.CurrentThread.CurrentCulture = ci;
    System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
    CultureInfo ci2 = CultureInfo.CreateSpecificCulture(ci.Name);

    //InputLanguageManager.SetInputLanguage(this.rtbDoc, CultureInfo.CreateSpecificCulture(ci2.Name));
    XmlLanguage xl = this.rtbDoc.Document.Language;
    XmlLanguage xl2 = XmlLanguage.GetLanguage(ci2.IetfLanguageTag);

    // this works in changing the property but nothing changes in the doc
    this.rtbDoc.Language = xl2;  

    if (this.rtbDoc.Selection.Text.Length > 1)
    {
        // this works to change the property and the spellchecker shows the entire 
        // doc content misspelled, but the selected text remains english
        this.rtbDoc.Selection.ApplyPropertyValue(FrameworkElement.LanguageProperty, xl2);  
    }

}

private void ChangeLanguage(object sender, RoutedEventArgs e)
    {
        defaultLanguage = InputLanguageManager.Current.CurrentInputLanguage;
        InputLanguageManager.Current.CurrentInputLanguage = CultureInfo.CreateSpecificCulture(ci.Name);

    }

private void ChangeToDefault(object sender, RoutedEventArgs e)
    {
        InputLanguageManager.Current.CurrentInputLanguage = defaultLanguage;

在获得 Shloime Rosenblum 先生的帮助后,我修改了我的代码并在此处发布给可能寻求相同解决方案的其他人。首先,无法更改选择中的现有文本。更好的解决方案是允许用户在键入时切换语言。下面的代码可以让这件事顺利而立即地完成。

首先为组合框构建列表。我选择使用 table 而不是带有 class 的列表,因为对我来说这更直观、更简单。

private void LoadLanguages()
    {
        CultureInfo[] ciCultures = CultureInfo.GetCultures(CultureTypes.AllCultures);

        // create table
        _dtLanguages = new DataTable();
        _dtLanguages.Columns.Add("LanguageId", typeof(int));
        _dtLanguages.Columns.Add("LanguageName", typeof(string));
        _dtLanguages.Columns.Add("LanguageDisplayName", typeof(string));

        // populate table
        foreach ( CultureInfo ci in ciCultures)
        {
            DataRow dr = _dtLanguages.NewRow();
            dr["LanguageId"] = ci.LCID;
            dr["LanguageName"] = ci.Name;
            dr["LanguageDisplayName"] = ci.DisplayName + "(" + ci.NativeName + ")";
            _dtLanguages.Rows.Add(dr);
        }

        try
        {
            _dtLanguages.DefaultView.Sort = "LanguageDisplayName ASC";
            this.cbbLanguage.ItemsSource = _dtLanguages.DefaultView;
            this.cbbLanguage.DisplayMemberPath = "LanguageDisplayName";
            this.cbbLanguage.SelectedValuePath = "LanguageId";
        }
        catch (Exception ex)
        {
            int i = ex.Message.Length;
        }

        return;
    }

然后为用户选择语言添加 selectionchanged 事件。

        private void cbbLanguage_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.AddedItems.Count == 0) { return; }

        // set language for rtb
        DataRowView drv = e.AddedItems[0] as DataRowView;
        DataRow[] dr = _dtLanguages.Select("LanguageId = " + drv[0].ToString());  // number id of language selected
        XmlLanguage xl2 = XmlLanguage.GetLanguage(dr[0]["LanguageName"].ToString());
        this.rtbDoc.Language = xl2;

        // set keyboard to match language setting; language must exactly match 
        // a keyboard defined in Windows.Control Panel.Language.Keyboards

        int iLcid = (int)this.cbbLanguage.SelectedValue;
        CultureInfo ci = new System.Globalization.CultureInfo(iLcid);
        InputLanguageManager.Current.CurrentInputLanguage = CultureInfo.CreateSpecificCulture(ci.Name);

        // rtb applies changes when receiving focus
        this.rtbDoc.Focus();
    }

用户选择语言并开始输入新语言,直到他选择另一种语言。无需更改 rtb 的 xaml 代码,也无需更改 rtb 焦点的事件。