WPF:从 ListItem 内容获取 TextRange
WPF: get TextRange from ListItem content
我正在尝试从 WPF FlowDocument ListItem 获取 TextRange:
var doc = new FlowDocument();
doc.Blocks.Add(new List(new ListItem(new Paragraph(new Run("first bullet")))));
如果我现在尝试使用
获取 TextRange
var range1 = new TextRange(doc.ContentStart, doc.ContentEnd);
或
var range2 = new TextRange(doc.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward), doc.ContentEnd);
我得到一个范围,其中文本 属性 returns
• first bullet
如果我尝试
var range3 = new TextRange(doc.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward).GetNextInsertionPosition(LogicalDirection.Forward), doc.ContentEnd);
正文属性returns
irst bullet
调试器显示:
range1.Start.Offset == 4
range2.Start.Offset == 4
range3.Start.Offset == 5
如何创建一个仅指向 "first bullet" 的 TextRange(没有项目符号和分隔符)?
这里的问题不在于 TextRange 本身(range1 恰好指向您需要的文本),而在于它的文本 属性。参考ITextRange.Text.
的实现
它使用更新的起始 TextPointer 调用 GetText(ITextRange thisRange) from TextRangeBase internal class, that intentionally moves starting TextPoiner backwards to include initial list marker (if any) and after that calls 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 bullet\r\n"
//text2: "•\tfirst bullet\r\n"
我正在尝试从 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);
我得到一个范围,其中文本 属性 returns
• first bullet
如果我尝试
var range3 = new TextRange(doc.ContentStart.GetNextInsertionPosition(LogicalDirection.Forward).GetNextInsertionPosition(LogicalDirection.Forward), doc.ContentEnd);
正文属性returns
irst bullet
调试器显示:
range1.Start.Offset == 4
range2.Start.Offset == 4
range3.Start.Offset == 5
如何创建一个仅指向 "first bullet" 的 TextRange(没有项目符号和分隔符)?
这里的问题不在于 TextRange 本身(range1 恰好指向您需要的文本),而在于它的文本 属性。参考ITextRange.Text.
的实现它使用更新的起始 TextPointer 调用 GetText(ITextRange thisRange) from TextRangeBase internal class, that intentionally moves starting TextPoiner backwards to include initial list marker (if any) and after that calls 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 bullet\r\n"
//text2: "•\tfirst bullet\r\n"