internal string Select(RichTextBox rtb, int index, int length)
{
TextRange textRange = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd);
if (textRange.Text.Length >= (index + length))
{
TextPointer start = textRange.Start.GetPositionAtOffset(index, LogicalDirection.Forward);
TextPointer end = textRange.Start.GetPositionAtOffset(index + length, LogicalDirection.Backward);
rtb.Selection.Select(start, end);
rtb.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.LightBlue));
}
return rtb.Selection.Text;
}
每当调用ApplyPropertyValue来更改所选文本的背景颜色时,它第一次运行良好,但在第二次调用时没有正确调整所选文本段的背景颜色。我怀疑这与调用函数后文档的偏移量有些混乱有关。
解决这个问题的好方法是什么?
答案 0 :(得分:6)
试试这个(它需要一个比你更复杂的逻辑),否则是:你有偏移问题!
private static TextPointer GetTextPointAt(TextPointer from, int pos)
{
TextPointer ret = from;
int i = 0;
while ((i < pos) && (ret != null))
{
if ((ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.Text) || (ret.GetPointerContext(LogicalDirection.Backward) == TextPointerContext.None))
i++;
if (ret.GetPositionAtOffset(1, LogicalDirection.Forward) == null)
return ret;
ret = ret.GetPositionAtOffset(1, LogicalDirection.Forward);
}
return ret;
}
internal string Select(RichTextBox rtb, int offset, int length, Color color)
{
// Get text selection:
TextSelection textRange = rtb.Selection;
// Get text starting point:
TextPointer start = rtb.Document.ContentStart;
// Get begin and end requested:
TextPointer startPos = GetTextPointAt(start, offset);
TextPointer endPos = GetTextPointAt(start, offset + length);
// New selection of text:
textRange.Select(startPos, endPos);
// Apply property to the selection:
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(color));
// Return selection text:
return rtb.Selection.Text;
}
然后以这种方式使用它(我在第一个字符中选择RED中的第五个字符):
this.Select(this.myRichTextBox, 0, 5, Colors.Red);
答案 1 :(得分:0)
首先,MAXE给出了很好的答案,因为它清楚地向我展示了我遇到的根本问题:需要记住WPF中的流文档控件处理的是标记,而不是原始文本。因此,潜在的问题是跳过标记,直到您实际处理包含元素内的文本。
这个解决方案的问题在于它非常慢。例如,一个选择大约150个文本的应用程序需要大约20秒才能使用这种方法执行,除了大约20ms之外的所有文本都花在选择文本上!
这个问题没有一般解决方案适用于所有场景,但仔细考虑您要实现的目标并进行相应优化是值得的。常见的情况是创建单个运行(段落等)并在其中放置一个文本块,然后选择/突出显示该单个元素中的文本。在这种情况下,您知道只有一个“元素”,因此您可以执行以下操作,从而获得与上述相同的结果:
internal static TextPointer GetOffsetTextPointer(this TextPointer start, int offset)
{
return start.GetInsertionPosition(LogicalDirection.Forward).GetPositionAtOffset(offset);
}
作为参考, GetInsertionPosition 方法将跳过起始元素标记,直到文本实际开始的位置,然后 GetPositionAtOffset 方法将实际指针放在一个单个电话。为了进行比较,上面的例子现在执行时间不到2秒。
答案 2 :(得分:0)
感谢MAXE提供这个出色的解决方案。
在rtf文本中使用换行符和其他不可见字符可能会遇到麻烦。要解决此问题,请在方法的开头添加偏移校正器:
$scope.$watchCollection("cart_list", function(newV, oldV){
if(newV and newV.length > 0)
{
// do your stuff
for(var i=0; newV.length; i++)
{
if(newV[i].order == "single")
console.log("with single order");
}
}
}, true);