Avatar billede simsen Mester
12. juli 2008 - 08:27 Der er 13 kommentarer og
3 løsninger

Treeview - find bestemt node

Hej,

Ja, jeg roder stadig med mit treeview og er ved at være lidt desperat....MEN har da naglet det ned nu, så håber en herinde kan hjælpe mig :-)

Min træ struktur ser ud som følgende:

Forside
Produkter
..Kategori 1
....Underkategori 1.1
....Underkategori 1.2
..Kategori 2

Altså den er på 3 niveauer.....

Jeg kan faktisk godt finde ud af at finde niveau 1 og 2 MEN den fejler hver gang i niveau 3..... med følgende:
"Index was out of range. Must be non-negative and less than the size of the collection."

Jeg kan ikke hitte ud af, hvad problemet er i min kode?

Koden:
try
        {
            string nodetext = "Kontakt os";           

            for (int i = 0; i < MenuTree.Nodes.Count; i++)
            {
                TreeNode headnode = MenuTree.Nodes[i];

                if (headnode.Text == nodetext)
                {
                    headnode.PopulateOnDemand = false;
                    headnode.Expand();
                    headnode.Selected = true;
                }
                else
                {
                    foreach (TreeNode node in MenuTree.Nodes[i].ChildNodes)
                    {
                        if (node.Text == nodetext)
                        {
                            node.PopulateOnDemand = false;
                            headnode.Expand();
                            node.Selected = true;
                        }
                        else
                        {
                            for (int j = 0; j < MenuTree.Nodes[i].ChildNodes.Count; i++)
                            {                                   
                                foreach (TreeNode subnode in MenuTree.Nodes[i].ChildNodes[j].ChildNodes)
                                {
                                    //TreeNode subnode = MenuTree.Nodes[i].ChildNodes[j];
                                    if (subnode.Text == nodetext)
                                    {
                                        subnode.PopulateOnDemand = false;
                                        //node.PopulateOnDemand = false;
                                        //headnode.Expand();
                                        node.Expand();
                                        subnode.Selected = true;
                                    }
                                }
                            }
                        }
                    }
                }
            }

Koden der er problemer med er den inderste løkke:

for (int j = 0; j < MenuTree.Nodes[i].ChildNodes.Count; i++)
                            {                                   
                                foreach (TreeNode subnode in MenuTree.Nodes[i].ChildNodes[j].ChildNodes)
                                {
                                    //TreeNode subnode = MenuTree.Nodes[i].ChildNodes[j];
                                    if (subnode.Text == nodetext)
                                    {
                                        subnode.PopulateOnDemand = false;
                                        //node.PopulateOnDemand = false;
                                        //headnode.Expand();
                                        node.Expand();
                                        subnode.Selected = true;
                                    }
                                }
                            }

Mvh
simsen :-)
Avatar billede montago Praktikant
12. juli 2008 - 09:25 #1
Du skal lære at lave rekursive funktioner når du har med træer at gøre... din kode bliver meget bedre :-)


public node FindNode(TreeNode node, string Search)
{
  if( node.Text == Search)
    return node;
  else
  {
      foreach(TreeNode sub in node.ChildNodes)
        FindNode(sub, Search);
  }
}

så kan du smide alle 'nodes' i dit TreeView eller din root node in i funktionen

på dit TreeView kan du sætte SelectedNode til at være den node som bliver returneret.
Avatar billede simsen Mester
12. juli 2008 - 09:57 #2
Hejsa montago,

Jeg har forsøgt mig med følgende:

string nodetext = "Om os"; 

            for (int i = 0; i < this.MenuTree.Nodes.Count; i++)
            {
                FindNode(MenuTree.Nodes[i], nodetext);

                node headnode = // Hvordan henter jeg returværdien ud???
                if (headnode.Text == nodetext)
                {
                    headnode.PopulateOnDemand = false;
                    headnode.Expand();
                    headnode.Selected = true;
                }
            }

Men den fejler ved din metode og siger følgende:
The type or namespace name 'node' could not be found (are you missing a using directive or an assembly reference?)

Hvilken using directive mangler jeg? (jeg bruger VS2008) og ikke mindst - hvordan henter jeg returværdien ud?.

Har jeg ret, hvis jeg læser din metode til kun at hente 2 niveauer ud og ikke 3, som er det, der er mit problem?

mvh
simsen :-)

mvh
simsen :-)
Avatar billede montago Praktikant
12. juli 2008 - 10:03 #3
Nu skal du bare se :o)
læg denne klasse i samme fil, eller som seperat class-file

public static class MyExtensions
{
    public static void FindAndSelect(this TreeView TV, string SearchText)
    {
        TreeNode found;
        foreach (TreeNode node in TV.Nodes)
        {
            found = node.FindNode(SearchText);
            if (found != null)
                break;
        }
        TV.SelectedNode = found;
    }

    public static TreeNode FindNode(this TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
            return node;
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                return FindNode(sub, SearchText);
            }

        return null;
    }
}


Herved kan du bruge en ny metode på dit TreeView :

TreeView TV = new TreeView();

TV.FindAndSelect("Søgetext");
Avatar billede montago Praktikant
12. juli 2008 - 10:08 #4
ønsker du at træet skal være collapsed, og kun noder nedtil den fundne skal være åbne ?

så kan du udvide extension metoden således:

public static class MyExtensions
{
    public static void FindAndSelect(this TreeView TV, string SearchText)
    {
        TV.CollapseAll();

        TreeNode found;
        foreach (TreeNode node in TV.Nodes)
        {
            found = node.FindNode(SearchText);
            if (found != null)
                break;
        }
        TV.SelectedNode = found;
        found.ExpandUpwards();
    }

    public static TreeNode FindNode(this TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
            return node;
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                return FindNode(sub, SearchText);
            }

        return null;
    }

    public static void ExpandUpwards(this TreeNode node)
    {
        node.Expand();

        if (node.Parent != null)
            ExpandUpwards(node.Parent);
    }
}
Avatar billede montago Praktikant
12. juli 2008 - 10:12 #5
hehehe...


kunne være jeg skulle spørge om det er .NET 2.0, 3.0 eller 3.5 !!
Avatar billede simsen Mester
12. juli 2008 - 10:21 #6
Jeg er ked af det - lige nu forsøger jeg kun at sætte din static classe ind i en cs (klasse fil) der i forvejen har flere static classes.....og den fejler med ikke mindre end 14 ting - jeg tager de to første:

1) Type expected (som er ved første linie (this) keywordet)
2) Identifier expected, 'string' is a keyword    (som er ved første linie (string) keywordet)

Jeg har de samme using direktiver stående. Jeg forsøgte så også at kopiere klassen ind i samme fil og får samme fejl?

Kan vi starte forfra - for jeg har en anden metode (som er hentet fra nettet af og som ER rekursiv.....) Problemet er stadig mit 3. niveau. Hvis jeg bruger metoden og søger på 1. eller 2. niveau - ekspander den pænt derhen hvor den nu skal være...Men forsøger jeg at finde en på 3. niveau, ekspander den ingenting - jeg kan dog se at den vælger den korrekte (har lagt node id'et ud i en label inde i metoden). Kan du fortælle mig, hvad fejlen er på den 3. niveau?

Koden for metoden er:
protected void retrieveNodes(TreeNode node)
    {
        if (node.Text == "Kontakt os")
        {
            node.PopulateOnDemand = false;
            node.Expand();
            node.Selected = true;
        }
        else
        {
            if (node.ChildNodes.Count != 0)
            {
                foreach (TreeNode tn in node.ChildNodes)
                {
                    if (tn.Text == "Kontakt os")
                    {
                        node.PopulateOnDemand = false;
                        tn.PopulateOnDemand = false;
                        node.Expand();
                        tn.Expand();
                        tn.Selected = true;
                    }
                    else
                    {
                        if (tn.ChildNodes.Count != 0)
                        {
                            retrieveNodes(tn);
                        }
                    }
                }
            }
        }
    }


Mvh
simsen :-)
Avatar billede simsen Mester
12. juli 2008 - 10:22 #7
Det er VS 2008 men på framework 2.0
Avatar billede montago Praktikant
12. juli 2008 - 10:22 #8
... Hvis du er helt forvirret...

den extension du har fået, erstatter alt den kode du har posted her på siden...

dvs. slet koden, og brug den nye metode på TreeView...
Avatar billede simsen Mester
12. juli 2008 - 10:28 #9
Jeg ER forvirret - jeg har slettet alt - undtaget i min pageload at hente menuen ind.....

Nu har jeg så tilføjet din static klasse og får stadig fejlene som beskrevet først i 10:21:32 - altså det er som om den ikke vil finde noget som helst - er det pga. frameworket?

Du skriver at jeg skal bruge metoden på TreeView - hvor henne mener du?
Avatar billede montago Praktikant
12. juli 2008 - 10:32 #10
ahh ok... .NET 2.0 har ikke extensions...
det ENESTE using direktiv min kode kræver er "System.Web.UI.WebControls;"
her får du metoderne, som rekursive (non-extensions):

Den metode du lige har posted er IKKE rekursiv !

brug disse metoder:

    public static void FindAndSelect(TreeView TV, string SearchText)
    {
        TV.CollapseAll();

        foreach (TreeNode node in TV.Nodes)
        {
            FindNode(node, SearchText);
        }
    }

    public static void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
            ExpandUpwards(node);
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                FindNode(sub, SearchText);
            }
    }

    public static void ExpandUpwards(TreeNode node)
    {
        node.Expand();

        if (node.Parent != null)
            ExpandUpwards(node.Parent);
    }

//--------


TreeView TV = new TreeView();

FindAndSelect(TV, "Søgetext");
Avatar billede simsen Mester
12. juli 2008 - 10:37 #11
Hmmmmm - jeg er møj møj dum - men hvor binder jeg den til mit treeview henne - altså mit TreeView har jeg kaldt MenuTree..........?

Koden kører fint - fejler ikke - men gør heller ingenting ved min menu nemlig
Avatar billede simsen Mester
12. juli 2008 - 10:43 #12
Jeg ER dum - jeg ved jo godt hvordan jeg binder den til mit treeview *lyserødmer*

Og jeg kunne altså kysse dig (og ja ja jeg ER kvinde)........din kode virker bare perfekt......

Rigtig mange tak for hjælpen - jeg har knoklet rundt med det her i snart 3 uger og forsøgt mig med mindst 50 forskellige ting, jeg har fundet på nettet....... Så du har gjort mig MEGET glad :-)
Avatar billede montago Praktikant
12. juli 2008 - 10:53 #13
nu må du lige spænde hjelmen :o)

her er et eksempel på det hele :

    <form id="form1" runat="server">
    <div>
        <asp:TextBox ID="TextBox1" Text="lag2.0" runat="server"></asp:TextBox>
        <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
        <asp:TreeView runat="server" ID="myTree"
            onselectednodechanged="myTree_SelectedNodeChanged"></asp:TreeView>
    </div>
    </form>

//--------------------

    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            myTree.Nodes.Add(new TreeNode("lag1.0"));
            myTree.Nodes.Add(new TreeNode("lag1.1"));
            myTree.Nodes[1].ChildNodes.Add(new TreeNode("lag2.0"));
            myTree.Nodes[1].ChildNodes.Add(new TreeNode("lag2.1"));
            myTree.Nodes.Add(new TreeNode("lag1.1"));
        }
    }
   
    public static void FindAndSelect(TreeView TV, string SearchText)
    {
        TV.CollapseAll();

        foreach (TreeNode node in TV.Nodes)
        {
            FindNode(node, SearchText);
        }
    }

    public static void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
            ExpandUpwards(node);
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                FindNode(sub, SearchText);
            }
    }

    public static void ExpandUpwards(TreeNode node)
    {
        node.Expand();

        if (node.Parent != null)
            ExpandUpwards(node.Parent);
    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        FindAndSelect(myTree, TextBox1.Text);
    }
    protected void myTree_SelectedNodeChanged(object sender, EventArgs e)
    {
        throw NotImplementedException();
    }
Avatar billede montago Praktikant
12. juli 2008 - 10:54 #14
... hov... fik ikke læst din kommentar, inden jeg postede...


godt det virker :-)
Avatar billede montago Praktikant
12. juli 2008 - 10:57 #15
en lille ting man skal have bag øret er, at TreeView ikke kaster en event hvis man trykker på den samme node 2 gange i træk... man skal/bør derfor de-select noden igen, efter man har behandlet trykket i eventhandleren...


men det må blive et andet spørgsmål :-D
Avatar billede montago Praktikant
12. juli 2008 - 11:30 #16
glemte vidst en ting...

  public static void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
            ExpandUpwards(node);
        else

-->

  public static void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText){
            node.Select();
            ExpandUpwards(node);
        }else
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester