2009-11-18 35 views
5

我现在使用的方式时间太长,试图找出一个问题,我不认为这会很难。制作一个简单的搜索功能,使光标跳到(或突出显示)被搜索的单词

这里是处理:

我写使用C#和WPF一个小应用程序。

我有一个RichTextBox包含一个FlowDocument。

我在我的richtextbox下面添加了一个小文本框和一个按钮。

然后,用户键入他/她希望搜索的单词,然后按下按钮。

然后richtextbox将跳转到该单词的第一个出现位置。

它只是跳转到正确的行就足够了 - 它也可以选择,突出显示或放置光标 - 只要richTextBox滚动到该单词,任何事情都会执行。

继续按下按钮,然后跳到下一个单词出现,等等,直到文档结束。

正如我所说 - 我认为这是一个简单的任务 - 但我有严重的问题搞清楚这一点。

回答

13

这应该做的工作:

public bool DoSearch(RichTextBox richTextBox, string searchText, bool searchNext) 
{ 
    TextRange searchRange; 

    // Get the range to search 
    if(searchNext) 
    searchRange = new TextRange(
     richTextBox.Selection.Start.GetPositionAtOffset(1), 
     richTextBox.Document.ContentEnd); 
    else 
    searchRange = new TextRange(
     richTextBox.Document.ContentStart, 
     richTextBox.Document.ContentEnd); 

    // Do the search 
    TextRange foundRange = FindTextInRange(searchRange, searchText); 
    if(foundRange==null) 
    return false; 

    // Select the found range 
    richTextBox.Selection.Select(foundRange.Start, foundRange.End); 
    return true; 
} 

public TextRange FindTextInRange(TextRange searchRange, string searchText) 
{ 
    // Search the text with IndexOf 
    int offset = searchRange.Text.IndexOf(searchText); 
    if(offset<0) 
    return null; // Not found 

    // Try to select the text as a contiguous range 
    for(TextPointer start = searchRange.Start.GetPositionAtOffset(offset); start != searchRange.End; start = start.GetPositionAtOffset(1)) 
    { 
    TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length); 
    if(result.Text == searchText) 
     return result; 
    } 
    return null; 
} 

原因在FindTextInRangeUnfortunately的for()循环的range.Text剥离了非文本字符,所以在某些情况下,通过偏移计算的IndexOf将稍太低。

+0

它的工作就像一个魅力。 非常感谢你的回答,朋友。你不知道你帮了我多少。 祝您有美好的一天! – Sagi1981 2009-11-19 10:47:33

+0

FindTextInRange中的第一个返回值应该改为null,而不是false :) – Sagi1981 2009-11-19 11:56:04

+2

谢谢。当你输入一个想法并且不想去尝试它时会发生这种情况。我在我的答案中编辑了false - > null。 – 2009-11-19 14:41:11

1

我已经使用了不同的方法。 使用文本框设置关键字;这搜索按钮单击的关键字。 查找关键字;突出它并关注这个关键词。

// Index of Current Result Found (Counts Characters not Lines or Results) 
    private int IndexOfSearchResultFound; 
    // Start Position Index of RichTextBox (Initiated as 0 : Beggining of Text/1st Char) 
    private int StartOfSelectedKeyword; 
    private int EndOfSelectedKeyword; 

    private void btnSearch_Click(object sender, EventArgs e) 
    { 
     // Reset Keyword Selection Index. (0 is the Staring Point of the Keyword Selection) 
     IndexOfSearchResultFound = 0; 

     // Specify the End of the Selected Keyword; using txt_Search.Text.Lenght (Char Ammount). 
     EndOfSelectedKeyword = txt_Search.Text.Length; 

     // If txt_Search.Text is not Empty 
     if (txt_Search.Text.Length > 0) 
     { 
      // Find Keyword in RichTextBox.Text 
      IndexOfSearchResultFound = FindKeyword(txt_Search.Text.Trim(), StartOfSelectedKeyword, rtb_Hosts.Text.Length); 

      // If string was found in RichTextBox; Highlight it and Focus on Keyword Found Location 
      if (IndexOfSearchResultFound >= 0) 
      { 
       // Focus on Currently Found Result 
       rtb_Hosts.Focus(); 

       // Highlight the search string 
       rtb_Hosts.Select(IndexOfSearchResultFound, EndOfSelectedKeyword); 

       // Sets a new Starting Position (after the Position of the Last Result Found) 
       // To be Ready to Focus on the Next Result 
       StartOfSelectedKeyword = IndexOfSearchResultFound + EndOfSelectedKeyword; 
      } 
     } 
    } 


    private int FindKeyword(string _SearchKeyword, int _KeywordSelectionStart, int _KeywordSelectionEnd) 
    { 
     // De-Select Previous Searched String (Keyword) 
     if (_KeywordSelectionStart > 0 && _KeywordSelectionEnd > 0 && IndexOfSearchResultFound >= 0) 
     { rtb_Hosts.Undo(); } 

     // Set the return value to -1 by default. 
     int retVal = -1; 

     // A valid Starting index should be specified. 
     // if indexOfSearchText = -1, Means that Search has reached the end of Document 
     if (_KeywordSelectionStart >= 0 && IndexOfSearchResultFound >= 0) 
     { 
      // Find Keyword 
      IndexOfSearchResultFound = rtb_Hosts.Find(_SearchKeyword, _KeywordSelectionStart, _KeywordSelectionEnd, RichTextBoxFinds.None); 

      // Determine whether the text was found in richTextBox 
      retVal = IndexOfSearchResultFound; 
     } 
     // Return the index to the specified Keyword text. 
     return retVal; 
    } 

我还没能做到的唯一的事情就是回到第一搜索结果

0

这是将找到匹配最接近到光标处的变体。

private TextRange FindText(string findText) 
    { 
     var fullText = DoGetAllText(); 
     if (string.IsNullOrEmpty(findText) || string.IsNullOrEmpty(fullText) || findText.Length > fullText.Length) 
     return null; 

     var textbox = GetTextbox(); 
     var leftPos = textbox.CaretPosition; 
     var rightPos = textbox.CaretPosition; 

     while (true) 
     { 
     var previous = leftPos.GetNextInsertionPosition(LogicalDirection.Backward); 
     var next = rightPos.GetNextInsertionPosition(LogicalDirection.Forward); 
     if (previous == null && next == null) 
      return null; //can no longer move outward in either direction and text wasn't found 

     if (previous != null) 
      leftPos = previous; 
     if (next != null) 
      rightPos = next; 

     var range = new TextRange(leftPos, rightPos); 
     var offset = range.Text.IndexOf(findText, StringComparison.InvariantCultureIgnoreCase); 
     if (offset < 0) 
      continue; //text not found, continue to move outward 

     //rtf has broken text indexes that often come up too low due to not considering hidden chars. Increment up until we find the real position 
     var findTextLower = findText.ToLower(); 
     var endOfDoc = textbox.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward); 
     for (var start = range.Start.GetPositionAtOffset(offset); start != endOfDoc; start = start.GetPositionAtOffset(1)) 
     { 
      var result = new TextRange(start, start.GetPositionAtOffset(findText.Length)); 
      if (result.Text?.ToLower() == findTextLower) 
      { 
      return result; 
      } 
     } 
     } 
    } 

如果你想突出的匹配,那么当你发现匹配它会是为改变这种方法无效,这样做简单:

textbox.Selection.Select(result.Start, result.End);