Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: [VB.NET] Treeview duplicate nodes

kSiit [16.11.2011 21:37:49]

#

Morjes, eli olen tässä jonkin aikaa tuota vb.netiä koittanut harjoitella.
Ohjelmana käytän Visual Studio 2005.
Form, jossa TreeView (Treeview1) ja Painike (Button1), nappulaa painamalla treeview:n täyttyy.
Access -kanta (Database1), jossa table1, jossa kentät ID, Henkilö, Esine.
Eli tarkoitus on, että puunäkymä olisi seuraava:

Henkilö A
-------EsineA
-------EsineB
Henkilö B
-------EsineC

Mutta ongelmaksi muodostuu, että kyseisessä tilanteessa formille ilmestyy henkilö A 2 kertaa, eli:

Henkilö A
-------EsineA
-------EsineB
Henkilö A
-------EsineA
-------EsineB
Henkilö B
-------EsineC

Eli olisiko mahdollista estää nuo tuplaantuneet nodet?
Alla formin koodi

Imports System.Data.OleDb

Public Class Form9

    Inherits System.Windows.Forms.Form
    Dim olecon As OleDb.OleDbConnection
    Dim daHenkilö As OleDb.OleDbDataAdapter
    Dim daEsine As OleDb.OleDbDataAdapter
    Dim dsgeneral As DataSet

    Private Sub Form9_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load


        Try
            Dim Kanta As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Temp\Database1.mdb;User ID=Admin;Password="

            olecon = New OleDb.OleDbConnection(Kanta)
        Catch
            MsgBox(Err.Description)
            Exit Sub
        End Try


    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        TreeView1.Nodes.Clear()

        olecon.Open()


        daHenkilö = New OleDb.OleDbDataAdapter("select Henkilö from Table1", olecon)
        dsgeneral = New DataSet()

        daHenkilö.Fill(dsgeneral, "Henkilö")


        Dim I%, j%, Henkilö$, Esine$


        For I = 0 To dsgeneral.Tables("Henkilö").Rows.Count - 1

            Henkilö = dsgeneral.Tables("Henkilö").Rows(I).Item("Henkilö").ToString


            TreeView1.Nodes.Add(Henkilö)
            TreeView1.Nodes(I).ImageIndex = 0

            daEsine = New OleDb.OleDbDataAdapter("select * from Table1 where Henkilö='" & Henkilö & "'", olecon)

            daEsine.Fill(dsgeneral, "Esine")
            dsgeneral.Tables("Esine").Clear()
            daEsine.Fill(dsgeneral, "Esine")

            For j = 0 To dsgeneral.Tables("Esine").Rows.Count - 1


                Esine = dsgeneral.Tables("Esine").Rows(j).Item("Esine").ToString
                Dim EsineNode As TreeNode
                EsineNode = TreeView1.Nodes(I)

                EsineNode.Nodes.Add(Esine)



                EsineNode.Expand()


            Next


        Next



    End Sub



    Private Sub TreeView1_AfterCollapse(ByVal sender As Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterCollapse


    End Sub

    Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect

    End Sub
End Class

Grez [16.11.2011 21:49:15]

#

Kokeile korvata "select Henkilö from Table1" tällä "select distinct Henkilö from Table1"

Vaikka tuota koodia ja toimintalogiikkaa voisi siistiä paljonkin, niin en todellakaan jaksa hirveästi paneutua kun taulujen nimet on tyyliin "Table1", tietorakennetta ei ole kerrottu, jne.

Yleisesti ottaen sanoisin, että koko tietomassan voisit hakea yhdellä kyselyllä nykyisen n+1 kyselyn asemesta, missä n on kannassa oleva henkilöiden määrä.

neau33 [17.11.2011 18:08:22]

#

Moikka kSiit!

sinuna vääntelisin jutskan näin...

Imports System.Data
Imports System.Data.OleDb

Public Class Form1
   Inherits System.Windows.Forms.Form

   Dim olecon As OleDbConnection = Nothing
   Dim da As OleDbDataAdapter = Nothing
   Dim ds As DataSet = Nothing

   Private Sub Form1_Load(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles MyBase.Load
        Try
           Dim Kanta As String = _
           "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
           + "C:\Temp\Database1.mdb;User ID=Admin;Password="
           olecon = New OleDbConnection(Kanta)
        Catch
            MsgBox(Err.Description)
            Exit Sub
        End Try
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles Button1.Click

      Try
         olecon.Open
      Catch
         MsgBox(Err.Description)
         Exit Sub
      End Try

      treeView1.Nodes.Clear

      da = New OleDbDataAdapter( _
      "SELECT Henkilö, Esine FROM Table1", olecon)

      ds = New DataSet()
      da.Fill(ds, "Table1")
      da = Nothing

      Dim i As Integer

      For i = 0 To ds.Tables("Table1").Rows.Count - 1

         Dim dRow As DataRow = ds.Tables("Table1").Rows(i)

         TreeView1.Nodes.Add(dRow("Henkilö").ToString)
         TreeView1.Nodes(i).ImageIndex = 0

         Dim EsineNode As TreeNode = TreeView1.Nodes(i)

         'jos 'Esine' kenttä sisältää pilkulla (,)
         'erotettuja arvoja esim. (EsineA,EsineB,jne.) niin...
         If dRow("Esine").ToString.Contains(",") Then
            Dim strArray() As String = _
            dRow("Esine").ToString.Split(",".ToCharArray)
            For j As Integer = 0 To strArray.Length - 1
               EsineNode.Nodes.Add(strArray(j))
            Next j
            strArray = Nothing
         Else 'muutoin...
            EsineNode.Nodes.Add(dRow("Esine").ToString)
         End If

        EsineNode = Nothing
        dRow = Nothing

      Next i

      treeView1.ExpandAll
      olecon.Close
      ds = Nothing

   End Sub

   Private Sub Form1_FormClosing(ByVal sender As System.Object, _
   ByVal e As System.FormClosingEventArgs) Handles MyBase.FormClosing
      olecon = Nothing
   End Sub

End Class

Grez [17.11.2011 19:12:07]

#

Nean ajatus laittaa saman henkilöön esineet yhdelle riville pilkulla eroteltuna on kylläkin huonoa tietokantasuunnittelua eikä millään tavalla tarpeellinen edes usean kyselyn tekemisen välttämiseen.

Eli suosittelen olemaan menemättä huonompaan suuntaan tuossa asiassa.

neau33 [17.11.2011 21:03:21]

#

Moikka taas!

Grez: tietokannoissa on itsessään erinäistäkin erotinmerkeillä erotettua dataa vaikkei ehkä käyttäjälle näkyisikään. Huonoa suunnitteluako?

mutta väännellään nyt sitten näin...

Imports System.Data
Imports System.Data.OleDb

Public Class Form1
   Inherits System.Windows.Forms.Form

   Private olecon As OleDbConnection = Nothing

   Private Sub Form1_Load(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles MyBase.Load
        Try
           Dim Kanta As String = _
           "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" _
           + "C:\Temp\Database1.mdb;User ID=Admin;Password="
           olecon = New OleDbConnection(Kanta)
        Catch
            MsgBox(Err.Description)
            Exit Sub
        End Try
   End Sub

   Private Sub Button1_Click(ByVal sender As System.Object, _
   ByVal e As System.EventArgs) Handles Button1.Click

      Try
         olecon.Open
      Catch
         MsgBox(Err.Description)
         Exit Sub
      End Try

      treeView1.Nodes.Clear

      Dim da As OleDbDataAdapter = New OleDbDataAdapter( _
      "SELECT Henkilö, Esine FROM Table1", olecon)
      Dim ds As New DataSet

      da.Fill(ds, "Table1")
      da = Nothing
      olecon.Close

      For i As Integer = 0 To ds.Tables("Table1").Rows.Count - 1

         Dim dRow As DataRow = ds.Tables("Table1").Rows(i)
         Dim IsExisting As Boolean = False

         For j As Integer = 0 To TreeView1.Nodes.Count -1
            If TreeView1.Nodes(j).Text = dRow("Henkilö").ToString Then
               IsExisting = True: Exit For
            End If
         Next j

         If Not IsExisting Then
            TreeView1.Nodes.Add(dRow("Henkilö").ToString)
            TreeView1.Nodes(TreeView1.Nodes.Count - 1).ImageIndex = 0
            For j As Integer = 0 To ds.Tables("Table1").Rows.Count - 1
               If ds.Tables("Table1").Rows(j)("Henkilö") _
               .ToString = dRow("Henkilö").ToString Then
                  dRow = ds.Tables("Table1").Rows(j)
                  Dim EsineNode As TreeNode = _
                  TreeView1.Nodes(TreeView1.Nodes.Count - 1)
                  EsineNode.Nodes.Add(dRow("Esine").ToString)
                  EsineNode = Nothing
               End If
            Next j
         End If

         dRow = Nothing

      Next i

      treeView1.ExpandAll
      ds = Nothing

   End Sub

   Private Sub Form1_FormClosing(ByVal sender As System.Object, _
   ByVal e As System.FormClosingEventArgs) Handles MyBase.FormClosing
      olecon = Nothing
   End Sub

End Class

kSiit [17.11.2011 22:18:20]

#

Kiitoksia vastauksista, lähti kyllä tuolla "select distinct":lläkin toimimaan.
Mutta pitää katsoa tuo neau33:n vaihtoehto läpi, joka on varmasti parempi kuin tuo minun.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta