这是一篇很老的帖子,但也许有人会发现这个解决方案很有用。
不幸的是,搜索文本并确定其在 RichTextBox
中的位置是一个有点复杂的过程。由于文本可以包含不同的格式元素,例如背景/前景色、不同的字体、图像等,因此必须使用上下文来确定所需文本的位置。
一种可能的解决方案如下所示。
MainWindow.xaml
<Window ...
Title="MainWindow" Height="250" Width="400"
KeyDown="Window_KeyDown">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<RichTextBox Grid.Row="0" x:Name="rtb" AllowDrop="True"
VerticalScrollBarVisibility="Auto" Padding="2" FontSize="18"
HorizontalAlignment="Left" >
<FlowDocument>
<Paragraph>
<Run FontSize="10" Text="In this example,you will learn to print Hello World." />
<Run Text="In this example,you will learn to print Hello World." />
<Run FontSize="20" Text="In this example,you will learn to print Hello World." />
</Paragraph>
</FlowDocument>
</RichTextBox>
<Button Grid.Row="1" Click="Button_Click">Color Words</Button>
</Grid>
</Window>
MainWindow.xaml.cs
private void Button_Click(object sender,RoutedEventArgs e)
{
var pairs = new Dictionary<string,SolidColorBrush>(StringComparer.InvariantCultureIgnoreCase)
{
{ "hello",Brushes.Red },{ "world",Brushes.Blue }
};
// Define the range to be used to analyze for the specified words
var textRange = new TextRange(rtb.Document.ContentStart,rtb.Document.ContentEnd);
// Build list of Word/TextRange pairs
var list = CalculateTextRange(textRange,pairs.Select(d => d.Key).ToList());
// Color words by using calculated `TextRange`.
for (int i = 0; i < list.Count; i++)
{
list[i].Value.ApplyPropertyValue(TextElement.ForegroundProperty,pairs[list[i].Key]);
}
rtb.Focus();
}
public static IList<KeyValuePair<string,TextRange>> CalculateTextRange(TextRange range,IList<string> words)
{
// Building the regular expression pattern
var pattern = new StringBuilder(@"\b");
for (int i = 0; i < words.Count; i++)
{
if (i > 0) pattern.Append('|');
pattern.Append(words[i]);
}
pattern.Append(@"\b");
Regex regExp = new Regex(pattern.ToString(),RegexOptions.IgnoreCase);
TextRange search = range;
int correction = 0;
var result = new List<KeyValuePair<string,TextRange>>();
// Enumerate all found mathes and creating list of Word/TextRange pairs
foreach (Match match in regExp.Matches(range.Text))
{
if (CalculateTextRange(search,match.Index - correction,match.Length) is TextRange tr)
{
result.Add(new KeyValuePair<string,TextRange>(match.Value,tr));
correction = match.Index + match.Length;
search = new TextRange(tr.End,search.End);
}
}
return result;
}
// Calculates a `TextRange` of the string started from `iStart` index
// and having `length` size or `null`.
public static TextRange CalculateTextRange(TextRange search,int iStart,int length)
{
return (GetTextPositionAtOffset(search.Start,iStart) is TextPointer start)
? new TextRange(start,GetTextPositionAtOffset(start,length))
: null;
}
// Calculate `TextPointer` from defined text position by specified offset.
public static TextPointer GetTextPositionAtOffset(TextPointer position,int offset)
{
for (TextPointer current = position; current != null; current = position.GetNextContextPosition(LogicalDirection.Forward))
{
position = current;
var adjacent = position.GetAdjacentElement(LogicalDirection.Forward);
var context = position.GetPointerContext(LogicalDirection.Forward);
switch (context)
{
case TextPointerContext.Text:
int count = position.GetTextRunLength(LogicalDirection.Forward);
if (offset <= count)
{
return position.GetPositionAtOffset(offset);
}
offset -= count;
break;
case TextPointerContext.ElementStart:
if (adjacent is InlineUIContainer)
offset--;
break;
case TextPointerContext.ElementEnd:
if (adjacent is Paragraph)
offset -= 2;
break;
}
}
return position;
}
上面的代码包含 Button_Click()
处理程序,当用户点击 Color Words 按钮时,它会执行以下步骤。
- 定义要在
RichTextBox
中找到的单词列表和列表中每个单词的颜色(在本例中实际上是画笔):
var pairs = new Dictionary<string,Brushes.Blue }
};
- 定义用于分析指定词的范围。在此示例中,使用了整个
RichBoxText
文档:
var textRange = new TextRange(rtb.Document.ContentStart,rtb.Document.ContentEnd);
- 为列表中指定并在文档中找到的所有单词计算
TextRange
的列表:
// Build list of Word/TextRange pairs
var list = CalculateTextRange(textRange,pairs.Select(d => d.Key).ToList());
- 为所有找到的单词着色。
添加图片是为了检查即使在这种情况下也能正确计算位置。
本文链接:https://www.f2er.com/3117561.html