2013-09-24 81 views
2

我試圖在WPF RichTextBox中啓用拼寫檢查。 MSDN寫道System.Windows.Controls.SpellCheck可用於爲TextBox和RichTextBox控件啓用拼寫檢查。拼寫檢查不適用於WPF RichTextBox

不幸的是,下面的代碼不爲我工作:

<RichTextBox SpellCheck.IsEnabled="True" xml:lang="en-US"></RichTextBox> 

這是奇怪的,因爲如果我用一個簡單的文本框,它工作完全正常(我可以看到紅色的線,如果我miss-拼寫一些東西)。

不幸的是,everyanswer我對SO到目前爲止只提及設置SpellCheck.IsEnabledTrueLanguage屬性設置爲支持的語言中,但我不知道爲什麼會發生這種方法不是我的計算機上工作內置RichTextBoxes的情況?

更新:

如果我寫的是,在運行中的文本將帶有下劃線:

<RichTextBox SpellCheck.IsEnabled="True"> 
    <FlowDocument Language="en"> 
     <Paragraph> 
      <Run>asdfasdf</Run> 
     </Paragraph> 
    </FlowDocument> 
</RichTextBox> 

但不幸的是,如果我嘗試輸入一些其他文本,它將被忽略。它看起來像編輯的內容上的屬性Language未設置爲英語。我試圖設置即使Thread'sCurrentCultureCurrentUICulture沒有結果...

+1

它對我來說工作得很好。 – Paparazzi

+0

你能給我一些關於你測試什麼環境的暗示嗎?操作系統版本,.NET框架版本等... – Zsolt

+0

這不是一個有效的FlowDocument併爲我引發語法錯誤。第一級元素必須從Block開始運行並且不運行。嘗試一個有效的第一級元素,如段落。 – Paparazzi

回答

3

好吧,最後我已經找到了解決方案的問題。如果您深入瞭解WPF源代碼,可以很容易地看到問題:有一個名爲TextEditorTyping的內部類,它有一個名爲DoTextInput的方法,該方法負責插入用戶輸入字符。此方法通過在TextEditorTextEditor是另一個爲各種控件(例如RichTextBox)提供文本編輯服務的內部類)調用SetSelectedText來設置插入範圍的文化屬性。這裏是DoTextInput方法的一部分:

IDisposable disposable = This.Selection.DeclareChangeBlock(); 
using (disposable) 
{ 
    ITextSelection selection = This.Selection; 
    if (!This.AllowOvertype || !This._OvertypeMode) 
    { 
     flag = false; 
    } 
    else 
    { 
     flag = str != "\t"; 
    } 
    ((ITextRange)selection).ApplyTypingHeuristics(flag); 
    // SETTING THE CULTURE -> 
    This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage); 
    ITextPointer textPointer = This.Selection.End.CreatePointer(LogicalDirection.Backward); 
    This.Selection.SetCaretToPosition(textPointer, LogicalDirection.Backward, true, true); 
    undoCloseAction = UndoCloseAction.Commit; 
} 

所以方法是使用對應於Windows中的當前輸入語言的InputLanguageManager.Current.CurrentInputLanguage。如果使用與英語不同的輸入語言(這是FrameworkElement.LanguageProperty的默認值),那麼如果編輯RichTextBox中的文本,FlowDocument中的插入元素將使用當前輸入語言作爲其Language屬性。例如,如果您的輸入語言爲匈牙利語(hu-hu),您的FlowDocument應該是這樣的:

<FlowDocument> 
    <Paragraph> 
     <Run xml:lang="hu-hu">asdfasdf</Run> 
    </Paragraph> 
</FlowDocument> 

This site描述了同樣的問題。

幸運的是,有一個解決方法。 我們已經看到了DoTextInput方法的來源,並有一個使用塊中指出:

IDisposable disposable = This.Selection.DeclareChangeBlock(); 
using (disposable) 
{ 
    ... 
    // SETTING THE CULTURE -> 
    This.SetSelectedText(str, InputLanguageManager.Current.CurrentInputLanguage); 
    ... 
} 

這是一個被佈置在最後一行的變化塊 - 它被佈置之後,TextContainerChanged事件解僱我們可以通過重寫的RichTextBoxOnTextChanged方法處理:

protected override void OnTextChanged(TextChangedEventArgs e) 
{ 
    var changeList = e.Changes.ToList(); 
    if (changeList.Count > 0) 
    { 
     foreach (var change in changeList) 
     { 
      TextPointer start = null; 
      TextPointer end = null; 
      if (change.AddedLength > 0) 
      { 
       start = this.Document.ContentStart.GetPositionAtOffset(change.Offset); 
       end = this.Document.ContentStart.GetPositionAtOffset(change.Offset + change.AddedLength); 
      } 
      else 
      { 
       int startOffset = Math.Max(change.Offset - change.RemovedLength, 0); 
       start = this.Document.ContentStart.GetPositionAtOffset(startOffset); 
       end = this.Document.ContentStart.GetPositionAtOffset(change.Offset); 
      } 

      if (start != null && end != null) 
      { 
       var range = new TextRange(start, end); 
       range.ApplyPropertyValue(FrameworkElement.LanguageProperty, Document.Language); 
      } 
     } 
    } 
    base.OnTextChanged(e); 
} 

在這裏,我們重置編輯範圍的語言,以正確的價值 - 以Document.Language。 此解決方法後,您可以使用WPF拼寫檢查 - 例如,在法國:

<My:CultureIndependentRichTextBox xml:lang="fr-FR" SpellCheck.IsEnabled="True"> 
    <FlowDocument> 
    </FlowDocument> 
</My:CultureIndependentRichTextBox> 

它將神奇的工作。 :)