RichTextBox 双击选择由 "i.a." 等句点分隔的单词
RichTextBox double click selecting words separated by periods like "i.a."
我的目标是双击“i.a”的整个部分。像这样:
但是 WPF 的默认设置是单独选择字符串的每个部分:
样本:
<RichTextBox>
<FlowDocument>
<Paragraph>Reason for contact: i.a.</Paragraph>
</FlowDocument>
</RichTextBox>
从用户的角度来看,文本中可能会或可能不会涉及格式以突出显示关键字,但为“i.a”简化此操作。我认为不会涉及任何格式。可以格式化整个“word”,但不能像“i”是红色的,“a”是蓝色的。
到目前为止我发现了什么
我尝试使用 SpellCheck.CustomDictionaries
,选词不受这些影响。
TextEditorMouse class 负责在 SetCaretPositionOnMouseEvent 中启动选择,调用 IsAtCaretUnitBoundary 可能会检查单词边界,但我无法理解 TextPointer 的魔力。对我来说,似乎没有办法解决这个问题,因为它受到私有和内部方法的保护。
我怀疑 CaretPosition
的 TextPointer
通过查看对 System.Windows.Documents.TextPointerBase.GetWordRange(System.Windows.Documents.ITextPointer thisPosition, System.Windows.Documents.LogicalDirection direction)
4:
的调用来向前和向后涉及
System.Windows.Documents.TextPointer selectionStart = rtb.CaretPosition;
while (selectionStart.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text)
{
selectionStart = selectionStart.GetNextContextPosition(LogicalDirection.Backward);
}
System.Windows.Documents.TextPointer selectionEnd = rtb.CaretPosition;
while (selectionEnd.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
{
selectionEnd = selectionEnd.GetNextContextPosition(LogicalDirection.Forward);
}
如果假设分析文本没有格式可以考虑使用下面的代码:
private void Rtb_PreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var tr = GetWordByDelimiters();
// Color the selected text
tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
rtb.Focus();
e.Handled = true;
}
public TextRange GetWordByDelimiters()
{
TextPointer current = rtb.CaretPosition;
// \s matches any whitespace character (equivalent to [\r\n\t\f\v ])
string pattern = @"[^\s]+"; // Delimiters
// The run content before the current caret position
string backward = current.GetTextInRun(LogicalDirection.Backward);
// Scan text before caret
Match match = Regex.Match(backward, pattern, RegexOptions.RightToLeft);
TextPointer start = current;
if (match.Success && match.Index + match.Value.Length == backward.Length)
{
start = start.GetPositionAtOffset(-backward.Length + match.Index);
}
// The run content after the current caret position
string forward = current.GetTextInRun(LogicalDirection.Forward);
// Scan text after caret
match = Regex.Match(forward, pattern);
TextPointer end = current;
if (match.Success && match.Index == 0)
{
end = end.GetPositionAtOffset(match.Value.Length, LogicalDirection.Forward);
}
return new TextRange(start, end);
}
.xaml
的片段:
<RichTextBox x:Name="rtb" AllowDrop="True" VerticalScrollBarVisibility="Auto"
PreviewMouseDoubleClick="Rtb_PreviewMouseDoubleClick">
<FlowDocument>
...
</FlowDocument>
</RichTextBox>
如果有必要修改 pattern
以使用任何分隔符集。
我的目标是双击“i.a”的整个部分。像这样:
但是 WPF 的默认设置是单独选择字符串的每个部分:
样本:
<RichTextBox>
<FlowDocument>
<Paragraph>Reason for contact: i.a.</Paragraph>
</FlowDocument>
</RichTextBox>
从用户的角度来看,文本中可能会或可能不会涉及格式以突出显示关键字,但为“i.a”简化此操作。我认为不会涉及任何格式。可以格式化整个“word”,但不能像“i”是红色的,“a”是蓝色的。
到目前为止我发现了什么
我尝试使用 SpellCheck.CustomDictionaries
,选词不受这些影响。
TextEditorMouse class 负责在 SetCaretPositionOnMouseEvent 中启动选择,调用 IsAtCaretUnitBoundary 可能会检查单词边界,但我无法理解 TextPointer 的魔力。对我来说,似乎没有办法解决这个问题,因为它受到私有和内部方法的保护。
我怀疑 CaretPosition
的 TextPointer
通过查看对 System.Windows.Documents.TextPointerBase.GetWordRange(System.Windows.Documents.ITextPointer thisPosition, System.Windows.Documents.LogicalDirection direction)
4:
System.Windows.Documents.TextPointer selectionStart = rtb.CaretPosition;
while (selectionStart.GetPointerContext(LogicalDirection.Backward) != TextPointerContext.Text)
{
selectionStart = selectionStart.GetNextContextPosition(LogicalDirection.Backward);
}
System.Windows.Documents.TextPointer selectionEnd = rtb.CaretPosition;
while (selectionEnd.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
{
selectionEnd = selectionEnd.GetNextContextPosition(LogicalDirection.Forward);
}
如果假设分析文本没有格式可以考虑使用下面的代码:
private void Rtb_PreviewMouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
var tr = GetWordByDelimiters();
// Color the selected text
tr.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Yellow);
rtb.Focus();
e.Handled = true;
}
public TextRange GetWordByDelimiters()
{
TextPointer current = rtb.CaretPosition;
// \s matches any whitespace character (equivalent to [\r\n\t\f\v ])
string pattern = @"[^\s]+"; // Delimiters
// The run content before the current caret position
string backward = current.GetTextInRun(LogicalDirection.Backward);
// Scan text before caret
Match match = Regex.Match(backward, pattern, RegexOptions.RightToLeft);
TextPointer start = current;
if (match.Success && match.Index + match.Value.Length == backward.Length)
{
start = start.GetPositionAtOffset(-backward.Length + match.Index);
}
// The run content after the current caret position
string forward = current.GetTextInRun(LogicalDirection.Forward);
// Scan text after caret
match = Regex.Match(forward, pattern);
TextPointer end = current;
if (match.Success && match.Index == 0)
{
end = end.GetPositionAtOffset(match.Value.Length, LogicalDirection.Forward);
}
return new TextRange(start, end);
}
.xaml
的片段:
<RichTextBox x:Name="rtb" AllowDrop="True" VerticalScrollBarVisibility="Auto"
PreviewMouseDoubleClick="Rtb_PreviewMouseDoubleClick">
<FlowDocument>
...
</FlowDocument>
</RichTextBox>
如果有必要修改 pattern
以使用任何分隔符集。