2009-11-18 71 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);