我发现 wpf rtf 框返回的偏移量实际上毫无价值。他们没有考虑到文本框需要的隐藏字符。框中的每个新段落、图像等都会添加更多的隐藏字符,这些字符会扭曲偏移量。
这是我想出的搜索接近插入符号位置的匹配项。
private TextRange FindText(string findText)
{
var fullText = DoGetAllText();
if (string.IsNullOrEmpty(findText) || string.IsNullOrEmpty(fullText) || findText.Length > fullText.Length)
return null;
var textbox = GetTextbox();
var leftPos = textbox.CaretPosition;
var rightPos = textbox.CaretPosition;
while (true)
{
var previous = leftPos.GetNextInsertionPosition(LogicalDirection.Backward);
var next = rightPos.GetNextInsertionPosition(LogicalDirection.Forward);
if (previous == null && next == null)
return null; //can no longer move outward in either direction and text wasn't found
if (previous != null)
leftPos = previous;
if (next != null)
rightPos = next;
var range = new TextRange(leftPos, rightPos);
var offset = range.Text.IndexOf(findText, StringComparison.InvariantCultureIgnoreCase);
if (offset < 0)
continue; //text not found, continue to move outward
//rtf has broken text indexes that often come up too low due to not considering hidden chars. Increment up until we find the real position
var findTextLower = findText.ToLower();
var endOfDoc = textbox.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
for (var start = range.Start.GetPositionAtOffset(offset); start != endOfDoc; start = start.GetPositionAtOffset(1))
{
var result = new TextRange(start, start.GetPositionAtOffset(findText.Length));
if (result.Text?.ToLower() == findTextLower)
{
return result;
}
}
}
}
如果您想突出显示匹配项,那么只需将此方法更改为 void 并在找到匹配项时执行此操作:
textbox.Selection.Select(result.Start, result.End);