我正在尝试从WPF FlowDocument ListItem获取TextRange:
var doc = new FlowDocument();
doc.Blocks.Add(new List(new ListItem(new Paragraph(new Run("first bullet")))));
如果我现在尝试使用
获取TextRangevar 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(没有子弹和分离标签)?
答案 0 :(得分:2)
这里的问题不在TextRange本身( range1 完全指向您需要的文本),而是在Text属性中。我们来参考ITextRange.Text的实现。
它从TextRangeBase内部类调用GetText(ITextRange thisRange),故意将TextPoiner向后移动到包含初始列表标记(如果有),之后调用{{ 3}}更新了启动TextPointer。
这种行为可以用反思重现:
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 bullet\r\n"
//text2: "•\tfirst bullet\r\n"