[VB.NET] Treeview + Subnodes (van Subnodes)

Pagina: 1
Acties:
  • 156 views sinds 30-01-2008

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
Voor een stage project moet ik in een treeview een soort van bestands structuur inladen. Echter dit gaat dmv een database.
Ik loop echter tegen een groot probleem aan, het lukt me niet om subnodes van subnodes te maken.

Dit is wat ik wil:
Afbeeldingslocatie: http://www.perfect-id.com/screen/sc-nodes_subnodes.jpg

Dit is het database ontwerp voor dit verhaal:
3 kolommen; menunummer, menuomschrijving, submenu

Bij het ontwerpen van de database had ik het volgende idee
2, Producten, 0
3, Brio-lijn, 2
4, Brio Reports, 3
5, Brio Whatsoever, 3
Oftewel: submenu linkt aan het menunummer om de relatie binnen de treeview aan te geven.

Het lukt me tot 1 laag diep, daarna loopt het in de soep (dus Producten -> Brio-lijn) krijg ik nog voor mekaar, echter die 3de laag lukt me niet :S
Voor tot die 2de laag heb ik de volgende code geproduceerd;
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Clear()
        c3_contentbeheer.c3_dsvullen_bestandsoverzicht()

        c3_cb_recaantal = c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Tables _& 
("c3_bestandsoverzicht").Rows.Count
        c3_cb_recaantal = c3_cb_recaantal - 1

        For x = 0 To c3_cb_recaantal
            c3_cb_dbrecord = c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Tables & _
("c3_bestandsoverzicht").Rows(c3_cb_reccount)
            c3_cb_menunummer = CStr(c3_cb_dbrecord("menunummer"))
            c3_cb_menuomschrijving = CStr(c3_cb_dbrecord("menuomschrijving"))
            c3_cb_menutype = CStr(c3_cb_dbrecord("menutype"))
            c3_cb_submenu = CStr(c3_cb_dbrecord("submenu"))
            c3_cb_paginanummer = CStr(c3_cb_dbrecord("paginanummer"))

            If Not c3_cb_reccount = c3_cb_recaantal Then
                c3_cb_reccount = c3_cb_reccount + 1
            End If

            Dim tag As Integer
            If c3_cb_menutype <> 0 Then
                For y = 0 To tvCBbestandsoverzicht.Nodes.Count - 1
                    tag = tvCBbestandsoverzicht.Nodes.Item(y).Tag
                    If c3_cb_submenu = tag Then
                        tvCBbestandsoverzicht.Nodes(y).Nodes.Add(c3_cb_menunummer, & _
c3_cb_menuomschrijving).Tag = c3_cb_menunummer
                    End If
                Next y
            End If
        Next x

[ Voor 7% gewijzigd door MikevanEngelen op 22-09-2004 10:17 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Je zult het met een recursieve functie moeten doen.

Die functie roep je aan om de items op te halen die je aan je node wilt hangen, en roep je ook voor iedere nieuwe node aan.

https://fgheysels.github.io/


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
whoami schreef op 22 september 2004 @ 10:18:
Je zult het met een recursieve functie moeten doen.

Die functie roep je aan om de items op te halen die je aan je node wilt hangen, en roep je ook voor iedere nieuwe node aan.
Hier had de (c++) programmeur binnen het bedrijf het ook al over, echter het probleem is dat ik niet weet wat het is, en met name ik het moet gebruiken binnen dit project.

Zou je mij eventueel een voorbeeld kunnen geven (in ieder geval dat hij die sub van sub items kan aanmaken ?) van een "recursive" functie ? (liefst natuurlijk iets dat gerelateerd is aan het werken met een treeview).
Ik heb ook al een code voorbeeld gezien van aan recursive functie binnen C#, maar na lang uit proberen (en omzetten naar vb.net) is het me niet gelukt. (mede omdat het een voorbeeld was met directorys, lokaal op een hdd).

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Even een heel simpel voorbeeldje van een recursieve functie die ook een beetje je probleem oplost
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Class Node
{
AddNodes( int id )
{
   int[] subnodes = GetSubNodes( id );
   foreach( int subID in subnodes )
   {
       //voeg niewe node toe

       nieuweNode.AddNodes( subID );
   }
}
}

Oke zo is het niet echt bruikbaar maar ik hoop dat je het idee een beetje snapt. Een recursieve functie is niets meer dan een functie die zichzelf weer aanroept. het belangrijkste is om te zorgen dat er wel ergens een eind aan de functie zit anders blijft hij oneindig lang doorgaan. Met een tree zal je daar waarschijnlijk niet zoveel last van hebben aangezien een node op een gegeven moment gewoon geen subnodes meer heeft.

[ Voor 10% gewijzigd door Woy op 22-09-2004 11:05 . Reden: Even de code wat aangepast. ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
rwb schreef op 22 september 2004 @ 10:59:
Even een heel simpel voorbeeldje van een recursieve functie die ook een beetje je probleem oplost
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Class Node
{
AddNodes( int id )
{
   int[] subnodes = GetSubNodes( id );
   foreach( int subID in subnodes )
   {
       //voeg niewe node toe

       nieuweNode.AddNodes( subID );
   }
}
}

Oke zo is het niet echt bruikbaar maar ik hoop dat je het idee een beetje snapt. Een recursieve functie is niets meer dan een functie die zichzelf weer aanroept. het belangrijkste is om te zorgen dat er wel ergens een eind aan de functie zit anders blijft hij oneindig lang doorgaan. Met een tree zal je daar waarschijnlijk niet zoveel last van hebben aangezien een node op een gegeven moment gewoon geen subnodes meer heeft.
In welke taal is dat, als ik me C# > VB.NET converter gebruik komt er geen code uit rollen maar allemaal commentaar.

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Het is een beetje pseudo achtige code, maar het ging meer om het idee.

[ Voor 31% gewijzigd door Woy op 22-09-2004 11:34 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
Ok, maar het lost het probleem niet op dat het me niet niet lukt "dynamisch" subnodes van subnodes aan te maken...

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Als je al C# code hebt, moet je die zelf makkelijk kunnen omzetten naar VB.NET.
Als je een beetje programmeur bent, moet je zo door de code heen kunnen kijken. Een programmeur is nl. niet iemand die een bepaalde taal spreekt (C# bv.) maar iemand die de concepten die hij moet coderen (of die door anderen gecodeerd zijn) snapt.
Als je dat dus snapt, dan weet je wat er gebeurt, en kan je die instructies makkelijk omzetten naar een andere taal.

Als je een beetje de moeite neemt om die pseudo-code van rwb te bekijken (en niet verwacht dat het kant en klare code is die je zo kunt gebruiken; het is hier nl. geen McDonalds-afhaaldienst voor kant en klare code), kan je het concept makkelijk toepassen op jouw project.

Als je dat niet wilt, of niet kunt snappen, dan kan je maar beter iets anders gaan doen. Zandkastelen bouwen ofzo.

Het gaat er dus om dat je method zichzelf opnieuw aanroept om de sub-nodes te gaan creeëren van de net gecreeërde node.

https://fgheysels.github.io/


  • Christoph
  • Registratie: Februari 2000
  • Niet online
MikevanEngelen schreef op 22 september 2004 @ 11:50:
Ok, maar het lost het probleem niet op dat het me niet niet lukt "dynamisch" subnodes van subnodes aan te maken...
Hij probeert je ook gewoon op weg te helpen ipv je code voor te schotelen, lees even je help file over recursive procedures.
Of je library.

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Heel simpel.
Je maakt eerst een Hashtable aan. In die hashtable stop je elke node die je aanmaakt, met menunummer als key en de treenode als value.

Dan haal je de lijst met menus op uit de database. Dan maak je een 2e hashtable van nodes die een parent (submenu) hebben die nog niet is aangemaakt.
Je loopt dan de lijst af die je uit de database hebt gehaald. Per rij maak je een node aan. Die stop je in je 1e hashtable. Je kijkt of de node met de key van het submenu van de rij al is aangemaakt. Zo ja, dan voeg je de nieuwe node als node toe aan de nodes collection van de node met als key waarde de waarde van het submenu. Zo nee, dan voeg je je node toe aan de 2e hashtable, als key de row, en als value de node.

Wanneer je klaar bent heb je wellicht nog wat nodes in de 2e hashtable zitten, dan doorloop je die nog eens van voor naar achter: Per DictionaryEntry in de hashtable (met een for each doorlopen) haal je dan de submenu node op uit de 1e hashtable, voegt de node (de value van die entry in de 2e hashtable) toe aan de nodes van de submenu node.

Wanneer je ook daarmee klaar bent, is je tree klaar. Je bewaart de 1e hashtable, zodat je, wanneer er menu nodes bijkomen in de database, je meteen de node hebt waaraan deze moeten worden gehangen.

In code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Dim submenuToNode As New Hashtable()  ' make member of class

Dim orphanNodes As New Hashtable()
Dim rootNode As New TreeNode("root")
tvCBbestandsoverzicht.Nodes.Add(rootNode)
submenuToNode.Add(0, rootNode)

c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Clear()
c3_contentbeheer.c3_dsvullen_bestandsoverzicht()

c3_cb_recaantal = c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Tables & _ 
("c3_bestandsoverzicht").Rows.Count
c3_cb_recaantal = c3_cb_recaantal - 1

For x = 0 To c3_cb_recaantal
    ' do something about these horrible names!!
    ' vvvvvvvvvvv
    c3_cb_dbrecord = c3_contentbeheer.c3_cb_datas_bestandsoverzicht.Tables & _ 
("c3_bestandsoverzicht").Rows(c3_cb_reccount)
    c3_cb_menunummer = CStr(c3_cb_dbrecord("menunummer"))
    c3_cb_menuomschrijving = CStr(c3_cb_dbrecord("menuomschrijving"))
    c3_cb_menutype = CStr(c3_cb_dbrecord("menutype"))
    c3_cb_submenu = CStr(c3_cb_dbrecord("submenu"))
    c3_cb_paginanummer = CStr(c3_cb_dbrecord("paginanummer"))

    Dim newNode As New TreeNode(c3_cb_menuomschrijving)
    submenuToNode.Add(c3_cb_menunummer, newNode)
    If Not submenuToNode.ContainsKey(c3_cb_submenu) Then
        ' orphan, parent is not yet added.
        orphanNodes.Add(c3_cb_dbrecord, newNode)
    Else
        Dim parentNode As TreeNode = CType(submenuToNode(c3_cb_submenu), TreeNode)
        parentNode.Nodes.Add(newNode)
    End If
Next x

Foreach currentOrphan As DictionaryEntry In orphanNodes
    Dim row As DataRow = CType(currentOrphan.Key, DataRow)
    Dim submenuID As String = row("submenu").ToString()
    Dim menuID As String = row("menunummer").ToString()
    If submenuToNode.ContainsKey(submenuID) Then
        ' parent is present in the tree, add it
        Dim parentNode As TreeNode = CType(submenuToNode(submenuID), TreeNode)
        parentNode.Nodes.Add(CType(currentOrphan.Value, TreeNode))
    Else
        ' treenode refers to submenu which is not part of the tree, bug in menu data
        submenuToNode.Remove(menuID)
    End If
Next

' Done!


Overigens is een recursieve variant erg inefficient, zoals die gegeven is door rwb, want je moet telkens de lijst ophalen. Deze routine loopt 1 keer door de rows en 1 keer door de orphans, en met een goede sortering van de rijen bij het ophalen heb je waarschijnlijk geen orphans.

[ Voor 19% gewijzigd door EfBe op 22-09-2004 12:21 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
EfBe schreef op 22 september 2004 @ 12:17:
Overigens is een recursieve variant erg inefficient, zoals die gegeven is door rwb, want je moet telkens de lijst ophalen. Deze routine loopt 1 keer door de rows en 1 keer door de orphans, en met een goede sortering van de rijen bij het ophalen heb je waarschijnlijk geen orphans.
Hier heb je natuurlijk gelijk in. Recursieve functies zijn bijna nooit de efficientste manier om iets te doen.
Je zou de recursieve manier natuurlijk ook kunnen combineren met een op parent gesorteerde lijst van alle nodes. Dan kan je relatief snel de children van een node ophalen.
Maar zoals jij het doet blijft inderdaad wel sneller. Maar het lijkt me voor de TS wel handig om eens wat onderzoek te doen naar recursieve functies. Die zijn soms heel erg handig om te gebruiken.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
EfBe, super bedankt voor je code !

Na enkele kleine wijzigen, doet het nu precies wat ik wil.
En ja ;) ik ben ook wat aan het doen aan die variabel / functie namen, voor mij zijn ze duidelijk. Maar toen ik ze liet zijn aan de c++ programmeur hier op het werk snapte hij er geen bout van...

In ieder geval bedankt. Verder wil ik ook de rest van de mensen bedanken welke me de goede richting op hebben geduwt.

Toch (weer?) een kleine opmerking naar whoami:
Niet iedereen kan goed programmeren, ik ben iemand die als er eenmaal een voorbeeld is geweest dat ik het idee snap. Echter als je uberhaupt je eigen programmeertaal al amper schrijft, kan je niet verwachten dat iemand anders zomaar een andere programmeer taal leest alsof je stuctuur doorneemt.
Sommige mensen zullen dat misschien best kunnen, ik niet.
Toch zal het eind resultaat wat ik produceer misschien code-technisch niet goed in mekaar zitten, echter het product wat ik (moet/ga) opleveren is wel functioneel en zit gebruikerstechnisch goed in mekaar.
Dus in het kort: probeer je eens in te leven in mensen die iets minder goed zijn in het programmeren, het wel willen, maar het gewoon nog niet goed kunnen. Ook jij hebt het ooit geleerd, op je eigen manier.

  • whoami
  • Registratie: December 2000
  • Laatst online: 16:52
Op de manier waarop je nu bezig bent zal je het nooit leren.
Had EfBe die code hier niet gedropt, dan ging je waarschijnlijk nog de moeite niet genomen hebben om enkele dingen zelf op te zoeken en zelf te gaan experimenteren.
Ik vraag me uberhaupt af of je de code die EfBe hier gepost heeft nu eigenlijk wel begrijpt. Je hebt nu misschien wel een werkend programma, maar ik ben 90% zeker dat er nu code in zit die je niet begrijpt.

https://fgheysels.github.io/


Verwijderd

Ik denk dat de de VB syntax inmiddels wel beheerst, maar de aanpak te direct is. Nu zou ik me meer toeleggen op algoritmes, bv gebruik van hashes, + en - van recursie, OOP, etc.

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
whoami schreef op 22 september 2004 @ 14:25:
Op de manier waarop je nu bezig bent zal je het nooit leren.
Had EfBe die code hier niet gedropt, dan ging je waarschijnlijk nog de moeite niet genomen hebben om enkele dingen zelf op te zoeken en zelf te gaan experimenteren.
Ik vraag me uberhaupt af of je de code die EfBe hier gepost heeft nu eigenlijk wel begrijpt. Je hebt nu misschien wel een werkend programma, maar ik ben 90% zeker dat er nu code in zit die je niet begrijpt.
Dat ik hier nu nog op in ga... zucht...

Ik ben over het algemeen iemand die zeker niet zo snel een vraag stelt in een forum of nieuwsgroep. Pas als ik uitgebreid geprobeerd heb om gegevens te krijgen en te verwerken in het programma, en dat blijft continu maar mislukken. Ja dan besluit ik om te posten in een forum of nieuwsgroep.
Echter zegt nog steeds niets over de skills van iemand met het programmeren. Toevallig heb ik de code wel aardig ontleed en snap nu zeker wel wat hij met die code doet.

Wat ik daaruit wel heb geconcludeerd is dat ik totaal verkeerd zocht, het voorbeeld wat Efbe geeft is ook niet recursive (eej, grappig dat ik dat weet, tsha heb de code doorgenomen en opgezocht hoe het werkt). Dat de code van efbe me helpt is duidelijk, echter dat wil niet zeggen dat als ik een vergelijkend iets nodig heb dat ik toch weer door me vorige projecten loop, en dat ik ga kijken naar bruikbare code die ik dan opnieuw doorneem en dan verander naar mijn behoefte binnen dat project.

Ik vind dat je wel erg snel conclusies trekt over andere mensen of dat zij wel of niet kunnen programmeren, of dat ze er in zijn geinteresseert.
Jij zal misschien een opleiding als programmeur hebben gehad (iets van technisch informatica), ik heb een opleiding als systeembeheerder. Met de basis van visual basic .net (waaruit blijkt dat ze me geen stuctuur hebben aangeleerd, etc).

Ook jij bent begonnen ooit met programmeren (misschien als hobby, misschien wist je het al lang omdat een van je ouders programmeur is/was). Niet iedereen ligt het programmeren zo makkelijk als jou, houd daar eens rekening mee.

  • MikevanEngelen
  • Registratie: Mei 2001
  • Laatst online: 22-05 14:39
Verwijderd schreef op 22 september 2004 @ 14:57:
Ik denk dat de de VB syntax inmiddels wel beheerst, maar de aanpak te direct is. Nu zou ik me meer toeleggen op algoritmes, bv gebruik van hashes, + en - van recursie, OOP, etc.
Inderdaad, dat is puur het gene wat mij is aangeleerd op school.
Puur de basis van het programmeren. Wat zijn functies, classes, users controls, etc. Verder niets.

Nu ben ik bezig met iets "moeilijkere" code, en loop ik tegen kleine probleempjes aan.

Ik ga nu dus ook meer concenteren op hoe bepaalde dingen werken in vb. De basis heb ik nu wel door. Dus inderdaad het leren hoe hashes werken (wat het uberhaupt zijn) etc. Dat is me volgende stap.

Step-by-step.

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 19:24

gorgi_19

Kruimeltjes zijn weer op :9

* gorgi_19 ziet weinig programmeerdiscussie hier meer in, dus dicht

[ Voor 10% gewijzigd door gorgi_19 op 22-09-2004 15:16 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo

Pagina: 1

Dit topic is gesloten.