在WPF RichTextBox Control中获取单词光标的方法是打开的

我想知道如何在WPF RichTextBox中获得当前光标所在的单词。 我知道RichTextBox有Selection属性。 但是,这只给了我RichTextBox中突出显示的文本。 相反,即使整个单词没有突出显示,我也想知道光标所在的单词。

任何提示都表示赞赏。

非常感谢你。

将此函数附加到任意RichTextBox(现在称为testRTB),并查看结果的“输出”窗口:

private void testRTB_MouseUp(object sender, MouseButtonEventArgs e) { TextPointer start = testRTB.CaretPosition; // this is the variable we will advance to the left until a non-letter character is found TextPointer end = testRTB.CaretPosition; // this is the variable we will advance to the right until a non-letter character is found String stringBeforeCaret = start.GetTextInRun(LogicalDirection.Backward); // extract the text in the current run from the caret to the left String stringAfterCaret = start.GetTextInRun(LogicalDirection.Forward); // extract the text in the current run from the caret to the left Int32 countToMoveLeft = 0; // we record how many positions we move to the left until a non-letter character is found Int32 countToMoveRight = 0; // we record how many positions we move to the right until a non-letter character is found for (Int32 i = stringBeforeCaret.Length - 1; i >= 0; --i) { // if the character at the location CaretPosition-LeftOffset is a letter, we move more to the left if (Char.IsLetter(stringBeforeCaret[i])) ++countToMoveLeft; else break; // otherwise we have found the beginning of the word } for (Int32 i = 0; i < stringAfterCaret.Length; ++i) { // if the character at the location CaretPosition+RightOffset is a letter, we move more to the right if (Char.IsLetter(stringAfterCaret[i])) ++countToMoveRight; else break; // otherwise we have found the end of the word } start = start.GetPositionAtOffset(-countToMoveLeft); // modify the start pointer by the offset we have calculated end = end.GetPositionAtOffset(countToMoveRight); // modify the end pointer by the offset we have calculated // extract the text between those two pointers TextRange r = new TextRange(start, end); String text = r.Text; // check the result System.Diagnostics.Debug.WriteLine("[" + text + "]"); } 

根据您是否也希望保留数字,将Char.IsLetter(...)更改为Char.IsLetterOrDigit(...)或其他任何其他内容。

提示:将其提取到单独程序集中的扩展方法中,以便在需要时访问它。

好吧,为了解决这个问题,我粗暴地强迫它。

我使用了curCaret.GetTextInRun(LogicalDirection.Backward)curCaret.GetTextInRun(LogicalDirection.Forward)

preCaretString.LastIndexOf(" ")postCaretString.IndexOf(" ")以及分隔单词并获得子串的其他分隔postCaretString.IndexOf(" ")一起使用。

最后我添加了字符串的前半部分和字符串的后半部分来获取当前的光标字。

我敢打赌,有更聪明的方法,但至少这解决了这个问题

您可以通过CaretPosition获取光标的当前位置。

不幸的是,没有简单的方法让角色位于插入符号位置的左/右。 我知道从RichTextBox中获取文本的唯一方法是在这个答案中 ,这有点令人费解。 但它将完成必要的工作。

由于单词是用空格划分的,因此您可以遍历插入符号周围的运行,直到找到空格。 即使RichTextBox甚至包含不同的字体和字体大小,此function也应该有效。

  public string GetWordByCaret(LogicalDirection direction) { // Get the CaretPosition TextPointer position = this.CaretPosition; TextPointerContext context = position.GetPointerContext(direction); string text = string.Empty; // Iterate through the RichTextBox based on the Start, Text and End of nearby inlines while (context != TextPointerContext.None) { // We are only interested in the text here //, so ignore everything that is not text if (context == TextPointerContext.Text) { string current = position.GetTextInRun(direction); // The strings appended based on whether they are before the caret or after it... // And well...I love switches :) switch (direction) { case LogicalDirection.Backward: { int spaceIndex = current.LastIndexOf(' '); // If space is found, we've reached the end if (spaceIndex >= 0) { int length = current.Length - 1; if (spaceIndex + 1 <= length) { text = current.Substring(spaceIndex + 1, length - spaceIndex) + text; } return text; } else text = current + text; } break; default: { int spaceIndex = current.IndexOf(' '); // If space is found, we've reached the end if (spaceIndex >= 0) { int length = current.Length; if (spaceIndex <= length) { text += current.Substring(0, spaceIndex); } return text; } else text += current; } break; } } // Move to the next position position = position.GetNextContextPosition(direction); // Get the next context if (position != null) context = position.GetPointerContext(direction); else context = TextPointerContext.None; } return text; } 

现在你可以像这样得到你关心的词。

  string before = GetWordByCaret(LogicalDirection.Backward); string after = GetWordByCaret(LogicalDirection.Forward); string word = before + after; // :) 

这是我使用LINQ和依赖属性的替代解决方案:

 public class SelectionRichTextBox : RichTextBox { public SelectionRichTextBox() { // Use base class style SetResourceReference(StyleProperty, typeof(RichTextBox)); } public static readonly DependencyProperty SelectedWordProperty = DependencyProperty.Register( "SelectedWord", typeof(string), typeof(SelectionRichTextBox), new PropertyMetadata("") ); public string SelectedWord { get { return (string)GetValue(SelectedWordProperty); } set { SetValue(SelectedWordProperty, value); } } protected override void OnMouseUp(MouseButtonEventArgs e) { TextPointer cursorPosition = CaretPosition; string strBeforeCursor = cursorPosition.GetTextInRun(LogicalDirection.Backward); string strAfterCursor = cursorPosition.GetTextInRun(LogicalDirection.Forward); string wordBeforeCursor = strBeforeCursor.Split().Last(); string wordAfterCursor = strAfterCursor.Split().First(); string text = wordBeforeCursor + wordAfterCursor; SelectedWord = string.Join("", text .Where(c => char.IsLetter(c)) .ToArray()); base.OnMouseUp(e); } } 

之后,你可以像这样在绑定中使用它: