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;

            SearchableTreeView.TreeSearchState treeSearchState = SearchableTreeView.TreeSearchState.NotStarted;

            // A SubSearch function is used to search part of the tree
            SubSearch(e.SearchRegularExpression, Nodes, searchFromBelow, originalSelectionStart, ref treeSearchState);
            if (treeSearchState == SearchableTreeView.TreeSearchState.MatchMade)
            {
                e.Successful = true;// We have a match
            }
            else if (treeSearchState != SearchableTreeView.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            = SearchableTreeView.TreeSearchState.Started;

                // Search first half of the document
                SubSearch(e.SearchRegularExpression, Nodes, null, originalSelectionStart, ref treeSearchState);
                if (treeSearchState == SearchableTreeView.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 SearchableTreeView.TreeSearchState state)
        {
            foreach (TreeNode treeNode in treeNodeCollection)
            {
                if (state == SearchableTreeView.TreeSearchState.Started) // Has the search started?
                {
                    if (treeNode == stopAtNode)
                    {
                        state = SearchableTreeView.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 = SearchableTreeView.TreeSearchState.MatchMade;
                        return;
                    }
                }
                if (startAfterNode == treeNode)
                {
                    state = SearchableTreeView.TreeSearchState.Started;
                }

                // sub search child nodes
                SubSearch(regularExpression, treeNode.Nodes, startAfterNode, stopAtNode, ref state);
                if (state == SearchableTreeView.TreeSearchState.HitEndNode)
                {
                    return;
                }
                if (state == SearchableTreeView.TreeSearchState.MatchMade)
                {
                    return;
                }
            }
        }