Avatar billede simsen Mester
12. juli 2008 - 14:25 Der er 11 kommentarer og
1 løsning

Treeview - find bestemt node fortsat

Hej,

Jeg havde problemer med at expande et treeview, som jeg i dag har fået hjælp til.... Jeg har dog fundet en detalje, som er ret vigtig, som ikke er med..... Den selecter ikke den node, jeg har valgt, men top noden istedet.

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


Vil jeg så have fat i Underkategori 1.2, kører jeg nedenfor viste kode - men den selecter altså Kategori 1.

Hvordan skal jeg få den til også at selecte og ikke kun ekspande 1.2?

Koden som den ser ud nu:
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //16-06-2008 AS
            //Get the top menu
            try
            {
                DALMenu menu = new DALMenu();
                if (menu.EditGetTopMenu(MenuTree) == Status.Success)
                {
                    //Henter submenus
                    for (int i = 0; i < MenuTree.Nodes.Count; i++)
                    {
                        TreeNode headnode = MenuTree.Nodes[i];

                        GetSubNodes(headnode);

                        foreach (TreeNode node in MenuTree.Nodes[i].ChildNodes)
                        {
                            GetSubNodes(node);
                        }
                    }
                }
            }
            catch
            { }
        }
    }


    protected void MenuTree_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
    {
        try
        {
            int key_id = Convert.ToInt32(e.Node.Value);

            lblMenuId.Text = key_id.ToString();

            if (e.Node.Depth == 0)
            {
                TreeView t = (TreeView)sender;

                for (int i = 0; i < t.Nodes.Count; i++)
                {
                    if (t.Nodes[i] != e.Node)
                    {
                        t.Nodes[i].CollapseAll();
                    }
                }
            }
        }
        catch
        {
        }
    }

    protected void MenuTree_TreeNodeCollapsed(object sender, TreeNodeEventArgs e)
    {
        try
        {
            int key_id = Convert.ToInt32(e.Node.Value);

            lblMenuId.Text = key_id.ToString();
        }
        catch
        {
        }
    }


    protected void Button1_Click(object sender, EventArgs e)
    { 
        try
        {
            string nodetext = "Webshop";
            FindAndSelect(MenuTree, nodetext);

        }
        catch
        { }
    }

    private static void GetSubNodes(TreeNode node)
    {
        DALMenu submenu = new DALMenu();
        submenu.EditGetSubMenu(node);
    }


    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)
        {
            node.Select();
            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);
    }

mvh
simsen :-)
Avatar billede montago Praktikant
12. juli 2008 - 14:49 #1
hmm

Jeg har siddet og leget lidt med koden...

der kommer først en SelectedNodeChanged event når man skifter enten manuelt vælger 1 node, eller i koden vælger en, derefter en anden (ergo changed)


Jeg forstår ikke helt hvad du mener med at overnoden bliver valgt.. ?

er der et event som du ikke får rigtigt ?... eller læser du TreeView.SelectedNode for tidligt ?


:-)
Avatar billede simsen Mester
12. juli 2008 - 14:58 #2
Hej igen montago

Håbede du stadig var her :-)

Du snakker russisk nu *flov* Jeg har indtil nu kunnet se, når jeg har lavet alt det andet på min label, at den er ændret hver gang. Med din kode, får jeg overnoden i label'en. Det jeg ikke forstår. Det er som om, hvis jeg søger på en på niveau, så kommer den rigtige i lablen men hvis jeg søger på en af de underliggende niveauer, henter den overnoden til den jeg søger på.....håber du forstår mig.

Og når du nu skriver sådan til mig......så KUNNE jeg jo selvfølgelig forsøge at skrive id ud i lablen i en af dine metoder istedet for......troede bare den pr. automatik også gik in i TreeNodeExpanded metoden......

Vender lige frygtelig tilbage, når jeg har checket det :-)
Avatar billede montago Praktikant
12. juli 2008 - 15:11 #3
ahhhh


TreeNode Expanded eventet, sker jo kun for en node, som har undernoder !

det smarteste er nok, at kaste en event i FindNode() metoden sådan her:

1. jeg har lavet alle metoderne NON-Static
2. jeg har oprettet et event

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

        foreach (TreeNode node in TV.Nodes)
        {
            FindNode(node, SearchText);
        }
    }
   
    public class NodeFoundEvent : EventArgs{ public TreeNode node { get; set; } }
    public event EventHandler<NodeFoundEvent> NodeFound;
   
    public void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
        {
            node.Select();
            ExpandUpwards(node);
            if (NodeFound != null)
                NodeFound(this, new NodeFoundEvent { node = node });
        }
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                FindNode(sub, SearchText);
            }
    }

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

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

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

inde i Page_Load opretter du en event listener sådan her:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // din kode ....
        }

        this.NodeFound += new EventHandler<NodeFoundEvent>(_Default_NodeFound);
    }

    void _Default_NodeFound(object sender, _Default.NodeFoundEvent e)
    {
        throw new NotImplementedException();

        // hent noden sådan her
        // e.node
    }
Avatar billede simsen Mester
12. juli 2008 - 15:13 #4
Hmmmmm det kan godt tage lidt længere tid......for den vil den underlytme ikke finde min label - selv med find Control inde i dine metoder

            Label lblMenuId = (Label)FindControl("lblMenuId");
            lblMenuId.Text = node.Text;
Avatar billede simsen Mester
12. juli 2008 - 15:18 #5
Jeg har forsøgt mig med følgende:

    void _Default_NodeFound(object sender, _Default.NodeFoundEvent e)
    {
        throw new NotImplementedException();

        lblMenuId.Text = e.node;
    }

Og den kommer så med følgende fejl :

The type or namespace name '_Default' could not be found (are you missing a using directive or an assembly reference?)
Avatar billede simsen Mester
12. juli 2008 - 15:29 #6
Jeg aner altså ikke hvilket namespace den så skal under, for der står ikke noget i filen - du får lige al koden her:

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

public partial class Test_TestMenu : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            //16-06-2008 AS
            //Get the top menu
            try
            {
                DALMenu menu = new DALMenu();
                if (menu.EditGetTopMenu(MenuTree) == Status.Success)
                {
                    //Henter submenus
                    for (int i = 0; i < MenuTree.Nodes.Count; i++)
                    {
                        TreeNode headnode = MenuTree.Nodes[i];

                        GetSubNodes(headnode);

                        foreach (TreeNode node in MenuTree.Nodes[i].ChildNodes)
                        {
                            GetSubNodes(node);
                        }
                    }
                }
            }
            catch
            { }
        }

        this.NodeFound += new EventHandler<NodeFoundEvent>(_Default_NodeFound);
    }

    void _Default_NodeFound(object sender, _Default.NodeFoundEvent e)
    {
        //throw new NotImplementedException();

        lblMenuId.Text = e.node;
    }

    protected void MenuTree_TreeNodeExpanded(object sender, TreeNodeEventArgs e)
    {
        try
        {
            int key_id = Convert.ToInt32(e.Node.Value);

            lblMenuId.Text = key_id.ToString();

            if (e.Node.Depth == 0)
            {
                TreeView t = (TreeView)sender;

                for (int i = 0; i < t.Nodes.Count; i++)
                {
                    if (t.Nodes[i] != e.Node)
                    {
                        t.Nodes[i].CollapseAll();
                    }
                }
            }
        }
        catch
        {
        }
    }

    protected void MenuTree_TreeNodeCollapsed(object sender, TreeNodeEventArgs e)
    {
        try
        {
            int key_id = Convert.ToInt32(e.Node.Value);

            lblMenuId.Text = key_id.ToString();
        }
        catch
        {
        }
    }


    protected void Button1_Click(object sender, EventArgs e)
    { 
        try
        {
            string nodetext = "TestSide123";
            FindAndSelect(MenuTree, nodetext);

        }
        catch
        { }
    }

    private static void GetSubNodes(TreeNode node)
    {
        DALMenu submenu = new DALMenu();
        submenu.EditGetSubMenu(node);
    }


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

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

    public class NodeFoundEvent : EventArgs { public TreeNode node { get; set; } }
    public event EventHandler<NodeFoundEvent> NodeFound;

    public void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
        {
            node.Select();
            ExpandUpwards(node);
            if (NodeFound != null)
                NodeFound(this, new NodeFoundEvent { node = node });
        }
        else
            foreach (TreeNode sub in node.ChildNodes)
            {
                FindNode(sub, SearchText);
            }
    }

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

        if (node.Parent != null)
            ExpandUpwards(node.Parent);
    }
}
Avatar billede simsen Mester
12. juli 2008 - 15:36 #7
Jeg bliver desværre nødt til at smutte et par timer....skulle have været afsted for en halv time siden, så kan ikke trække den længere.....kommer på senere i dag.

Håber du fortsat gider hjælpe mig med den her. Lærer da hele tiden noget nyt med din hjælp :-)
Avatar billede montago Praktikant
12. juli 2008 - 16:21 #8
ohhhh

problemet er at da jeg oprettede event-listener'eren brugte visual studio min class'es navn...

gør følgende:

1. slet eventhandleren:  _Default_NodeFount(...)
2. slet listener'eren: this.NodeFound....

3. opret en ny, ved at skrive (i Page_Load) this.NodeFound +=
4. tryk på TAB knappen 2 gange for at oprette eventet automatisk

derefter kan du bruge e.node.Text :-)
//-----------

Følgende virker nok ikke i .NET 2.0:

public void FindNode(TreeNode node, string SearchText)
    {
        if (node.Text == SearchText)
        {
            node.Select();
            ExpandUpwards(node);
            if (NodeFound != null)
                NodeFound(this, new NodeFoundEvent { node = node });

//------

new NodeFoundEvent { node = node } <-- .NET 3.5 assignment

i .NET 2.0 skal man i stedet skrive:

NodeFoundEvent evt = new NodeFoundEvent();
evt.node = node;

hvorefter du kan putte evt, ind i --> NodeFound(this, evt);


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


beklager at det hele er så avanceret, men når du lige har fået styr på det. har du lært lidt om at bruge events, som kan blive meget nyttige i fremtiden ! :-)

jeg beklager også at jeg bruger .NET 3.5 kode... det er blevet en vane efterhånden :-)
Avatar billede montago Praktikant
12. juli 2008 - 16:29 #9
du kan også ændre alle steder hvor der står "_Default" til "_Test_TestMenu"

det er min klasse som hedder Default :-)


læg mærke til at NodeFoundEvent er en Klasse som jeg har oprettet. Denne indeholder en property af typen TreeNode, som du læser fra, efter eventet er sket.

///


for hulan da...
.NET 3.5:
public class NodeFoundEvent : EventArgs{ public TreeNode node { get; set; } }

.NET 2.0:

public class NodeFoundEvent : EventArgs
{
  TreeNode _node;
  public TreeNode node { get{return _node} set{_node = value} }
}

denne klasse kan eventuelt flyttes udenfor Test_TestMenu klassen INDEN du genopretter din eventhandler...
Avatar billede simsen Mester
12. juli 2008 - 18:27 #10
Det virker bare SÅ perfekt.

Og ja, er selv støt på et par steder med beskrivelser, der ville gøre min hverdag nemmere, hvis vi gik over til 3.5 frameworket (f.eks. get/set at jeg ikke skal lave en intern variabel (3.5 gør det bagved for mig) - for selv den dag i dag forstår jeg ikke hvorfor jeg skal lave sådan en variabel.....) Men desværre må jeg ikke gå over til framework 3.5 endnu.....

Nu vil jeg gerne forstå (ja, jeg er stadig kvinde og netop derfor), hvad det er jeg har lavet - så jeg forsøger lige at forklare og ikke mindst spørge:

I pageload går jeg ind og overskriver (er det overskrivning eller tilføjelse til den eksisterende?) den eksisterende nodefound event med en ny event, jeg så laver i:

void Test_TestMenu_NodeFound(object sender, Test_TestMenu.NodeFoundEvent e)
    {
        lblMenuId.Text = e.node.Value;
    }

I ovennævnte kunne jeg så lave forskellige ting, der så kommer til handling, hver gang der er fundet en ny node.

Her opretter jeg en ny instans af min eventhandling:
public class NodeFoundEvent : EventArgs
    {
        TreeNode _node;
        public TreeNode node
        {
            get{return _node;}
            set { _node = value; }
        }
    }

MEN så kommer det - hvad er den her til???????

    public event EventHandler<NodeFoundEvent> NodeFound;

Du får dine velfortjente points, men håber du gider give tilkende om jeg har forstået det korrekt og forklare mig hvad den sidste er til

mvh
simsen :-)
Avatar billede montago Praktikant
12. juli 2008 - 19:09 #11
public event EventHandler<NodeFoundEvent> NodeFound;

er SELVE eventet... NodeFoundEvent er den variabel som sendes til eventhandleren.

man kan lave event som "anonyme" uden et specifikt return object :

public event EventHander MitEvent;


et event, er noget man kan "tilmelde" sig... derfor '+=' eller afskrive sig fra igen '-=' ...

hvis man leger lidt med det, fanger man det hurtigt ;-)

Man skal bare passe på man ikke laver cirkulære event-køer som får dit program til at gå i hak...
Avatar billede montago Praktikant
12. juli 2008 - 19:12 #12
void Test_TestMenu_NodeFound(object sender, Test_TestMenu.NodeFoundEvent e)
    {
        lblMenuId.Text = e.node.Value;
    }

er din eventHandler (den 'Handler' eventet)

public class NodeFoundEvent : EventArgs

er EventArgumentet (EventArg)

blabla.EventNavn += new EventHandler<type>(metode);

er tilmeldingen
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