ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 10.10.2002

Diese Seite wurde zuletzt aktualisiert am 10.10.2002
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für den Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Schlüsselpfade

Zurück...


Anzeige

(-hg) mailto:hg_tvwfullkeypath@aboutvb.de

Ein für den Anwender komfortables Feature ist es sicherlich, wenn er die Knotenzweige in einem TreeView-Steuerelement beim nächsten Start Ihrer Anwendung im gleichen Öffnungszustand vorfindet wie beim letztmaligen Beenden der Anwendung. Auf den ersten Blick sieht das nach einer eher trivialen Aufgabe aus. Sie bräuchten beim Beenden der Anwendung nur die Schlüssel sämtlicher geöffneter ("expandierter") Knoten zu speichern und beim nächsten Start alles diese Knoten wieder zu expandieren.

Doch zum einen wäre das ein sehr ineffizientes Vorgehen - vor allem dann, wenn das TreeView-Steuerelement sehr viele Knoten enthalten sollte, und zudem noch sehr viele dieser Knoten in einer tief verzweigten Struktur geöffnet sein sollten.

Zum anderen wird dieses Verfahren fehl schlagen, wenn die Knotenstruktur noch nicht oder noch unvollständig gefüllt ist. Denn gerade bei umfangreichen und tiefen Strukturen empfiehlt es sich, einen Zweig erst beim erstmaligen Öffnen aktuell zu füllen (siehe auch "Baum mit hohlen Früchten"). Einen tiefer in der Struktur liegenden Knoten anhand seines Schlüssels zu identifizieren und zu öffnen, obwohl er beim anfangs noch vollständig geschlossenen Baum noch nicht vorhandenen ist, wird nicht funktionieren. Sie müssten für diesen Knoten erst den gesamten Zweig bis hin zur Wurzel nachladen - und dazu natürlich auch alle seine "Geschwister" auf der gleichen Ebene. Sicher werden Sie innerhalb der Datenbasis, auf der der Inhalt des TreeViews beruht, auch die dazu benötigten Eltern-Kind-Verhältnisse in irgend einer Form abgelegt haben und so einen Zweig rekonstruieren können. Doch wahrscheinlich wird auch das relativ aufwändig sein.

Erheblich effizienter bezüglich des ersten Punktes wäre, nur die Schlüssel der jeweils letzten Knoten eines Zweiges zu speichern, die noch Kind-Knoten haben und expandiert sind (die Expanded-Eigenschaft alleine ist nicht genügend aussagekräftig, da sie auch auf True gesetzt sein kann, ohne dass der betreffende Knoten Kind-Knoten hätte) und dann die Zweige zu diesen Knoten zu öffnen. Dieser Ansatz ist brauchbar, es ist aber immer noch das angeführten zweite Problem zu lösen, falls Sie die empfehlenswerte Technik der "hohlen" Knoten einsetzen.

Beschränken wir uns nun zunächst einmal darauf, den Schlüssel eines einzelnen Knotens zu speichern und anschließend seinen Zweig möglichst effizient wieder zu öffnen. Die Knoten zu speichern und die Zweige zu ihnen wieder zu öffnen, ist kein Problem, wenn die Zweigstruktur schon komplett geladen ist. Sie brauchen nur die EnsureVisible-Methode der anhand der Schlüssel identifizierten Knoten aufzurufen. Doch wenn die Struktur noch nicht geladen ist, haben Sie das bereits beschriebene Problem.

Der Gedanke ist daher nahe liegend, gleich die Schlüssel des gesamten oberhalb des Knotens liegenden Zweigpfades mit zu speichern und so beim Rekonstruieren gleich bequem zur Hand zu haben. Doch der Schlüsselpfad wird Ihnen leider nicht frei Haus geliefert, im Gegensatz zum Pfad der Knotentexte, die Ihnen von der Eigenschaft FullPath eines Knotens zur Verfügung gestellt wird.

Die folgende Funktion FullKeyPath liefert Ihnen den gewünschten Pfad der Schlüssel (Keys). Es empfiehlt sich, ein anderes Trennzeichen als beim FullPath zu verwenden. Denn falls Sie diesen in den Schlüsseln ablegen, wäre das Chaos perfekt (siehe "Knotenpfade knüpfen").

Public Function FullKeyPath(Node As Node, _
 Optional Separator As String = "^") As String
  Dim nPath As String
  Dim nNodeParent As Node
  
  nPath = Node.Key
  Set nNodeParent = Node.Parent
  Do While Not (nNodeParent Is Nothing)
    With nNodeParent
      nPath = .Key & Separator & nPath
      Set nNodeParent = .Parent
    End With
  Loop
  FullKeyPath = nPath
End Function

Das Expandieren eines Knoten anhand eines solchen Schlüsselpfades erledigt die folgende Funktion ExpandFullKeyPath.

Public Function ExpandFullKeyPath(TreeView As TreeView, _
 KeyPath As String, _
 Optional ByVal EnsureVisible As Boolean = True, _
 Optional ByVal SelectNode As Boolean, _
 Optional Separator As String = "^") As Node

  Dim nNode As Node
  Dim nKeys() As String
  Dim l As Long
  
  With TreeView
    With .Nodes

Zunächst wird geprüft, ob es sich die Mühe überhaupt "lohnt" - wenn der Pfad leer ist, oder überhaupt keine Knoten (also auch keine Wurzelknoten) vorhanden sind, wäre die weitere Ausführung witzlos.

      Select Case True
        Case Len(KeyPath) = 0, .Count = 0
          Exit Function
      End Select

Nun zerlegen wir mit der Split-Funktion den Pfad in seine Bestandteile (da es in Visual Basic 5 diese Funktion noch nicht gibt, können sie einen Ersatz dafür verwenden - siehe "Teile-Haberschaft").

      nKeys = Split(KeyPath, Separator)

Jetzt expandieren wir den Pfad von der Wurzel aufwärts - und hierbei kommen eben die Bestandteile des Schlüsselpfades ins Spiel. "Hohle" Knoten werden dabei der Reihe nach gefüllt - und damit sollte auch der jeweils nächste Knoten im Pfad vorhanden sein. Sollte dieser jedoch aus irgendeinem Grunde jedoch nicht mit geladen worden sein, können wir den Rest vergessen und verlassen die Funktion.

      On Error Resume Next
      For l = UBound(nKeys) To 0 Step -1
        Set nNode = .Item(nKeys(l))
        If Err.Number Then
          Exit Function
        Else
          nNode.Expanded = True
        End If
      Next 'l
    End With

Falls der letzte Knoten auch noch gleich selektiert werden soll (Übergabe von True im Optionalen Parameter SelectNode), setzen wir seine Selected-Eigenschaft auf True.

    If SelectNode Then
      nNode.Selected = True

Anderenfalls könnte er immerhin noch ins Bild gerollt werden (Übergabe von True im Optionalen Parameter EnsureVisible).

    ElseIf EnsureVisible Then
      nNode.EnsureVisible
    End If

Schließlich geben wir den Knoten zur weiteren Verwendung als Rückgabewert der Funktion zurück.

  Set ExpandFullKeyPath = nNode
End Function

Die oben angeführte Aufgabe, nur die Schlüssel(-pfade) derjenigen Knoten zu speichern, die noch Kind-Knoten haben und expandiert sind, erledigt die Funktion AllExpandedFullKeyPaths.

Public Function AllExpandedFullKeyPaths(TreeView As TreeView, _
 Optional KeySeparator As String = "^", _
 Optional NodeSeparator As String = "´") As String

  Dim nNode As Node
  Dim nNodeParent As Node
  Dim nNodeNext As Node
  Dim nNodes As Collection
  Dim nPaths As String

Zunächst ermitteln wir den Wurzelknoten des ersten in der Nodes-Collection enthaltenen Knotens. Dieser erste Knoten ist nicht unbedingt ein Wurzelknoten, und auch nicht oberste Wurzelknoten, da die Reihenfolge in der Nodes-Collection relativ willkürlich ist und von der Reihenfolge des Einfügens der Knoten in die Collection abhängt.

  Set nNode = TreeView.Nodes(1)
  Set nNodeParent = nNode.Parent
  Do While Not (nNodeParent Is Nothing)
    Set nNode = nNodeParent
    Set nNodeParent = nNode.Parent
  Loop

Von diesem Knoten brauchen wir schließlich den obersten Knoten.

  Set nNodeNext = nNode.FirstSibling

Mittels der im weiteren sich selbst rekursiv aufrufenden privaten Hilfsprozedur zFollowNode sammeln wir in einer Collection alle Knoten, deren Schlüsselpfade gespeichert werden sollen. Wir übergeben ihr der Reihe nach alle Wurzelknoten.

  Set nNodes = New Collection
  Do
    zFollowNode nNodeNext, nNodes
    Set nNodeNext = nNodeNext.Next
  Loop While Not (nNodeNext Is Nothing)

Schließlich ermitteln wir mit der bereits bekannten Funktion FullKeyPath die Schlüsselpfade der gesammelten Knoten und fügen sie zu einem einzigen, bequem speicherbaren String zusammen.

  For Each nNode In nNodes
    With nNode
      nPaths = nPaths & NodeSeparator & _
       FullKeyPath(nNode, KeySeparator)
    End With
  Next
  If Len(nPaths) Then
    AllExpandedFullKeyPaths = Mid$(nPaths, 2)
  End If
End Function

Private Sub zFollowNode(Node As Node, Nodes As Collection)
  Dim nNodeChild As Node
  Dim nNodeParent As Node
  
  On Error Resume Next
  With Node
    If .Expanded Then
      If .Children Then
        Nodes.Add Node, .Key
        Set nNodeParent = .Parent
        If Not (nNodeParent Is Nothing) Then
          Nodes.Remove nNodeParent.Key
        End If
        Set nNodeChild = .Child
        Do
          zFollowNode nNodeChild, Nodes
          Set nNodeChild = nNodeChild.Next
        Loop While Not (nNodeChild Is Nothing)
      End If
    End If
  End With
End Sub

Der Trick in der Hilfsprozedur zFollowNode besteht darin, zunächst jeden Knoten in die Collection einzufügen, wenn er expandiert ist und Kind-Knoten hat. Nur solche Knoten wollen wir ja überhaupt speichern und somit einsammeln. Zugleich kann der gegebenenfalls auf höherer Ebene der rekursiven Aufrufe bereits eingefügter Elternknoten des Knotens aus der Sammlung wieder herausfallen. Die Kind-Knoten des Knotens werden auch nur dann untersucht, wenn er selbst expandiert ist.

Der letzte Schritt zur Wiederherstellung des Expansionszustandes der Zweigstruktur ist nun einfach. In der Prozedur ExpandAllKeyPaths wird der Sammelstring der zu expandierenden Knoten in einzelne Schlüsselpfade zerlegt und der Knoten zu jedem Schlüsselpfad wird expandiert.

Public Sub ExpandAllKeyPaths(TreeView As TreeView, _
 KeyPaths As String, Optional KeySeparator As String = "^", _
 Optional NodeSeparator As String = "´")

  Dim nPaths() As String
  Dim l As Long
  
  Select Case True
    Case Len(KeyPaths) = 0, TreeView.Nodes.Count = 0
      Exit Sub
  End Select
  nPaths = Split(KeyPaths, NodeSeparator)
  For l = 0 To UBound(nPaths)
    ExpandFullKeyPath TreeView, nPaths(l), , , , KeySeparator
  Next 'l
End Sub

Beispiel-Projekt und Modul modTvwFullKeyPath (tvwfullkeypath.zip - ca. 5,4 KB)


Artikel
Zum Download-Bereich dieses Artikel
Mail an den Autor dieses Artikels

KnowHow
Zur KnowHow-Übersicht

KnowHow-Themen
Themen - Allgemeines
Themen - Entwicklungsumgebung (VB-IDE)
Themen - Forms
Themen - Steuerelemente (Controls)
Themen - Grafik
Themen - Dateien
Themen - UserControls
Themen - Einsteiger-Tipps
Themen - Wussten Sie...?

Übersicht nach Titeln in alphabetischer Reihenfolge
Übersicht nach Erscheinungsdatum

Schnellsuche




Zum Seitenanfang

Copyright © 1999 - 2017 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...

Download Internet Explorer