0

私はTreeViewを持っており、それらはすべてデータベースに保存されているフォルダーとファイルを含んでいます。これで、AjaxToolkitのオートコンプリート検索機能を使用して検索機能を作成しました。検索から得た値を持つノードを見つけるのに苦労していることを除いて、すべて問題ありません。今では再帰的な方法である必要がありますが、その方法がわかりません。

だから、問題はです。すでに持っているノード値に基づいて、ツリービューでノードを見つけるにはどうすればよいですか。また、すべての親ノード値を取得する必要があります。だから私はこれからノードを選択することができます。

コードの一部を次に示します(検索が完了した後のポストバックにあります)。

 else
            {   
                // postBack handler for AJAX AutoComplete Extender - JavaScript call: AutoCompletedClientItemSelected
                if (Request.Form["__EVENTTARGET"] != null &&
                Request.Form["__EVENTTARGET"] == "AutoCompleteExtender" &&
                Request.Form["__EVENTARGUMENT"] != null)
                {   
                    //i have the value for the node, but i need to search for it here, 
                    //and i also need the node-values from all the parents. I need the "path"
                    string nodeValue = Session["NodeValueFromSearchForm"].ToString();
                    string nodePath = "";

                    foreach (TreeNode node in TreeViewFolders.Nodes)
                    {
                        if (node.Value == nodeValue)
                        {
                            //I'm stuck here
                            nodePath += "\\s" + node.Value;

                        }
                    }

                    string prompt = String.Format("<script>{0}{1}{2}</script>", "javascript:__doPostBack('TreeViewFolders','s", nodePath, "')");                    
                    ScriptManager.RegisterStartupScript(this, GetType(), "message", prompt, false);                    
                }
            }

ループではforeach、「ルート」フォルダー(上部)のみを取得しています。これを再帰的に実行して子ノードに到達し、最後に、一意のnode.valueを持つノードを見つけるにはどうすればよいですか?

GeorgesOatesLarsenの回答に感謝しますユーザーがツリービューにファイルをアップロードするときに、ノードのバリューパスを保存することだけを考えていませんでした。そのため、アップロードプロセスで「ファイル」テーブルに値パスを保存し、その値を__doPostBack

4

1 に答える 1

1

TreeViewオブジェクトがどの程度正確に機能するか、またはそのデータをどのように保存するか(または、独自のデータを保存するかどうか)は完全にはわかりません。ただし、ツリー検索アルゴリズムについては1つか2つ知っています。

あなたが探しているものを見つける最も速い方法は、主にあなたのツリーがソートされているかどうかに依存します。ソートされていないと仮定します。つまり、ソリューションにはO(N)の最悪のシナリオがあり、Nはツリー内のノードの数です。

さまざまな種類のツリーもあります。通常の古いツリー(任意の数の子、1つの親、1つのルートノード)を使用していると想定します。使用しているツリーに関する詳細情報を提供すると、ツリーをトラバースするための最良の方法に関するより良い情報を提供できます。

これらの仮定を前提とすると、擬似コードは次のようになります。

public TreeNode[] SearchTree(Tree YourTree, SearchObject SearchingFor)
{
    return SearchNode(0, YourTree.RootNode, SearchingFor);//Depth is sent in so that our recursion can keep track of how many parents the node has. This allows us to use simple arrays which are far faster than any alternative serial data storage.
}

public TreeNode[] SearchNode(int depth, TreeNode YourNode, SearchObject SearchingFor)
{
    //Edge case


    if (SearchingFor.Matches(YourNode))//Does the node match our search?
    {
        return GetHeritage(depth, YourNode);//We get the heritage at the end because it's faster than using a dynamically allocated array for every single recursion we do when only one will ever get used. That practically makes the memory used exponential! Not ot mention all of the slowdown caused by the algorithms required for reallocation.
    }


    //Recurse

    TreeNode[] ret = null;
    for (int i = 0; i < YourNode.ChildNodes.Length; i++)
    {
        //Set the ret temporary variable to our recursion, then see if it is null or not
        if ((ret = SearchNode(depth+1, YourNode.ChildNodes[i])) != null)
        {
            break;//Exit the loop!
        }
    }


    //Return the result

    return ret;//If we find the correct answer, the loop will break with ret at the correct value.
    //If, however, we do not find anything correct within this node, we will simply return null.
}



//Final calculation for the correct result.

public TreeNode[] GetHeritage(int depth, TreeNode YourNode)//This will list every node starting from the node we found going all the way back to the root node. The first element in the array returned will be the root node.
{
    TreeNode[] ret = new TreeNode[depth+1];
    ret[depth] = YourNode;//Depth is actually one less than our length, so... Hurrah!
    for (int i = depth; i >= 0; i--)
    {
        ret[depth-i] = ret[depth-(i-1)].Parent;
    }

    return ret;
}

編集:私はあなたのコメントのいくつかを読みました:

はるかに高速なアプローチは、単純に配列を作成し、TreeViewに何かを追加するたびに対応するノードを指す「自動インクリメントID」のインデックスを使用して各ノードへの参照を追加することです。次に、番号へのパスを取得するには、セカンダリ配列内のindex [number]にあるノードを確認し、その親をルートノードまでたどります。:)

于 2012-07-20T19:03:46.400 に答える