private void findDialog1_SearchRequested(object sender, SearchEventArgs e) { if (e.FirstSearch) { // Store the selection start position on the first search so that when all searches are complete // this fact can be reported to the user in the find dialog. originalSelectionStart = SelectedNode; } // First part of search is between item after current selection (inclusive) and the end of the // document (exclusive), or the original search position position (exclusive) if this is greater // than the current selection position TreeNode searchFromBelow = SelectedNode; TreeSearchState treeSearchState = TreeSearchState.NotStarted; // A SubSearch function is used to search part of the tree SubSearch(e.SearchRegularExpression, Nodes, searchFromBelow, originalSelectionStart, ref treeSearchState); if (treeSearchState == TreeSearchState.MatchMade) { e.Successful = true;// We have a match } else if (treeSearchState != TreeSearchState.HitEndNode) { // No match? We hit end of document // Retry from the beginning if the original start position is before or equal to the current selection e.RestartedFromDocumentTop = true; // The user is informed that the search started from the top treeSearchState = TreeSearchState.Started; // Search first half of the document SubSearch(e.SearchRegularExpression, Nodes, null, originalSelectionStart, ref treeSearchState); if (treeSearchState == TreeSearchState.MatchMade) { e.Successful = true; // We have a match } } }
/// <summary> /// A recursive 'sub search' command is used to search part of the tree /// </summary> /// <param name="regularExpression">The regular expression to use to match text</param> /// <param name="treeNodeCollection">The collection of nodes to search down from</param> /// <param name="startAfterNode">The node that searching actually begins from /// (otherwise just walk the tree until this node is found)</param> /// <param name="stopAtNode">A node to terminate the search at</param> /// <param name="state">Sends and returns the state of the recursive search</param> private void SubSearch(Regex regularExpression, TreeNodeCollection treeNodeCollection, TreeNode startAfterNode, TreeNode stopAtNode, ref TreeSearchState state) { foreach (TreeNode treeNode in treeNodeCollection) { if (state == TreeSearchState.Started) // Has the search started? { if (treeNode == stopAtNode) { state = TreeSearchState.HitEndNode; return; } if (nodeSearcher(treeNode, regularExpression)) { // We need to show search results even when the FindDialog is active // This means turning off HideSelection if it is set. // This unfortunately causes a slight flicker. One way to avoid this is to turn off HideSelection // in individual control instances. if (HideSelection) { // Ensure that the property is restored when the FindDialog is deactivated findDialog1.Deactivate += new EventHandler(RestoreHideSelection); HideSelection = false; } SelectedNode = treeNode; SelectedNode.EnsureVisible(); // Make sure the result node is visible state = TreeSearchState.MatchMade; return; } } if (startAfterNode == treeNode) { state = TreeSearchState.Started; } // sub search child nodes SubSearch(regularExpression, treeNode.Nodes, startAfterNode, stopAtNode, ref state); if (state == TreeSearchState.HitEndNode) { return; } if (state == TreeSearchState.MatchMade) { return; } } }