WPF:从列表项内容中获取文本范围



我正在尝试从 WPF FlowDocument ListItem 获取文本范围:

var doc = new FlowDocument();
doc.Blocks.Add(new List(new ListItem(new Paragraph(new Run("first bullet")))));

如果我现在尝试使用

var range1 = new TextRange(doc.ContentStart, doc.ContentEnd);

var range2 = new TextRange(doc.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward), doc.ContentEnd);

我得到一个 Text 属性返回的范围

•   first bullet

如果我尝试

var range3 = new TextRange(doc.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward).GetNextInsertionPosition(LogicalDirection.Forward), doc.ContentEnd);

Text 属性返回

irst bullet

调试器显示:

range1.Start.Offset == 4
range2.Start.Offset == 4
range3.Start.Offset == 5

如何创建一个仅指向"第一个项目符号"的文本范围(没有项目符号和分隔制表符(?

这里的问题不在于 TextRange 本身(range1 完全指向您需要的文本(,而在于其 Text 属性。让我们参考ITextRange.Text的实现。

它从 TextRangeBase 内部类调用 GetText(ITextRange thisRange(,它有意将起始 TextPoiner 向后移动以包含初始列表标记(如果有的话(,然后使用更新的起始 TextPointer 调用 GetTextInternal(ITextPointer startPosition,ITextPointer endPosition(。

可以通过反射重现此行为:

var textRangeBase  = typeof(TextRange).Assembly.GetType("System.Windows.Documents.TextRangeBase");
var getTextInternal = textRangeBase.GetMethod("GetTextInternal"
    , BindingFlags.NonPublic | BindingFlags.Static, null
    , new Type[] { typeof (TextPointer), typeof(TextPointer) }, null);
var text1 = getTextInternal.Invoke(null, new[] { range1.Start, range1.End });
var text2 = getTextInternal.Invoke(null, new[] { range1.Start
    .GetNextContextPosition(LogicalDirection.Backward)
    .GetNextContextPosition(LogicalDirection.Backward)
    .GetNextContextPosition(LogicalDirection.Backward)
    , range1.End });

//Results:
//text1: "first bulletrn"    
//text2: "•tfirst bulletrn"

最新更新