【问题标题】:Highlight parts of text in FlowDocument突出显示 FlowDocument 中的部分文本
【发布时间】:2013-09-16 15:06:28
【问题描述】:

我想根据搜索结果突出显示FlowDocument 中的某些文本部分。我正在做的是获取在FlowDocument的文本中出现搜索词的索引,然后在从找到的索引开始的文本范围上应用背景色,以找到的索引+搜索词长度结束。

TextRange content = new TextRange(myFlowDocument.ContentStart, 
                                  myFlowDocument.ContentEnd);
List<int> highlights = GetHighlights(content.Text, search);

foreach (int index in highlights)
{
    var start = myFlowDocument.ContentStart;
    var startPos = start.GetPositionAtOffset(index);
    var endPos = start.GetPositionAtOffset(index + search.Length);
    var textRange = new TextRange(startPos, endPos);
    textRange.ApplyPropertyValue(TextElement.BackgroundProperty, 
               new SolidColorBrush(Colors.Yellow));
}

TextRange newRange = new TextRange(myFlowDocument.ContentStart, 
                                   newDocument.ContentEnd);
FlowDocument fd = (FlowDocument)XamlReader.Parse(newRange.Text);

问题是,我正在搜索文档文本中的索引,但是当我返回 FlowDocument 时,添加了 xaml 标记并且我看到突出显示移动了。 我该如何解决?

【问题讨论】:

    标签: c# wpf highlight flowdocument


    【解决方案1】:

    最后,受到 user007 回答的启发,在进行了一些修改后,我设法突出显示了 FlowDocument 中字符串的所有出现。这是我的代码:

    for (TextPointer position = newDocument.ContentStart;
            position != null && position.CompareTo(newDocument.ContentEnd) <= 0;
            position = position.GetNextContextPosition(LogicalDirection.Forward))
    {
        if (position.CompareTo(newDocument.ContentEnd) == 0)
        {
            return newDocument;
        }
    
        String textRun = position.GetTextInRun(LogicalDirection.Forward);
        StringComparison stringComparison = StringComparison.CurrentCulture;
        Int32 indexInRun = textRun.IndexOf(search, stringComparison);
        if (indexInRun >= 0)
        {
            position = position.GetPositionAtOffset(indexInRun);
            if (position != null)
            {
                TextPointer nextPointer = position.GetPositionAtOffset(search.Length);
                TextRange textRange = new TextRange(position, nextPointer);
                textRange.ApplyPropertyValue(TextElement.BackgroundProperty, 
                              new SolidColorBrush(Colors.Yellow));
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您需要使用GetNextContextPosition(LogicalDirection.Forward) 进行迭代并获取TextPointer,将此与先前的TextPointer 一起使用以构造TextRange。在这个TextRange 上,你可以应用你的逻辑。

      你不能做的是使用来自FlowDocument 的单个 TextRange 来搜索文本。 FlowDocument 不仅仅是文字:

          private void Button_Click(object sender, RoutedEventArgs e)
          {
              String search = this.content.Text;
      
              TextPointer text = doc.ContentStart;
              while (true)
              {
                  TextPointer next = text.GetNextContextPosition(LogicalDirection.Forward);
                  if (next == null)
                  {
                      break;
                  }
                  TextRange txt = new TextRange(text, next);
      
                  int indx = txt.Text.IndexOf(search);
                  if (indx > 0)
                  {
                      TextPointer sta = text.GetPositionAtOffset(indx);
                      TextPointer end = text.GetPositionAtOffset(indx + search.Length);
                      TextRange textR = new TextRange(sta, end);
                      textR.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
                  }
                  text = next;
              }
          }
      

      更新: 它并非始终有效,例如,如果您有列表,则特殊字符 (\t) 会被 IndexOf 计算在内,但 GetPositionAtOffset 不会将它们计算在内:

      •   ListItem 1
      •   ListItem 2
      •   ListItem 3
      

      这一行:

      int indx = txt.Text.IndexOf(search);
      

      可以替换为:

      int indx = Regex.Replace(txt.Text, 
           "[^a-zA-Z0-9_.]+", "", RegexOptions.Compiled).IndexOf(search);
      

      【讨论】:

      • 非常感谢您的帮助。我正在尝试您的代码,但它仅突出显示搜索文本的第一次出现。我现在正在尝试对其进行修改以显示所有出现的情况。
      【解决方案3】:

      kzub 的答案似乎对我不起作用,因此我还创建了一个扩展 user007 的解决方案,以突出显示 TextPointer 文本中子字符串的所有实例。它还会忽略大小写并突出显示所有匹配项:

          public static void HighlightWords(TextPointer text, string searchWord, string stringText)
          {
              int instancesOfSearchKey = Regex.Matches(stringText.ToLower(), searchWord.ToLower()).Count;
      
              for (int i = 0; i < instancesOfSearchKey; i++)
              {
                  int lastInstanceIndex = HighlightNextInstance(text, searchWord);
                  if (lastInstanceIndex == -1)
                  {
                      break;
                  }
                  text = text.GetPositionAtOffset(lastInstanceIndex);
              }
          }
      
          private static int HighlightNextInstance(TextPointer text, string searchWord)
          {
              int indexOfLastInstance = -1;
      
              while (true)
              {
                  TextPointer next = text.GetNextContextPosition(LogicalDirection.Forward);
                  if (next == null)
                  {
                      break;
                  }
                  TextRange newText = new TextRange(text, next);
      
                  int index = newText.Text.ToLower().IndexOf(searchWord.ToLower());
                  if (index != -1)
                  {
                      indexOfLastInstance = index;
                  }
      
                  if (index > 0)
                  {
                      TextPointer start = text.GetPositionAtOffset(index);
                      TextPointer end = text.GetPositionAtOffset(index + searchWord.Length);
                      TextRange textRange = new TextRange(start, end);
                      textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
                  }
                  text = next;
              }
      
              return indexOfLastInstance;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-11-20
        • 2019-12-29
        • 2013-01-27
        • 2013-12-29
        • 2012-05-14
        • 2020-09-18
        • 2011-03-27
        相关资源
        最近更新 更多