Treeview & Pfade

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von woeh.

    Treeview & Pfade

    hallo....

    also ich habe einen hauptpfad, von dem unterpfade abgehen

    z.b.

    F:\_\1234\5678
    F:\_\1234\789\1234
    F:\_\1234\890
    F:\_\weerr\dddv\4rff
    F:\_\weerr\dddv\1234

    die pfade werden nach und nach übergeben und ich möchte die pfade dann in einem treeview darstellen.
    also wie man den ersten pfad einfügt weiß ich....

    aber jetzt möchte ich eben, das er mir die anderen pfade nicht seperat einfügt, sondern in den schon (wenn vorhanden) pfad.

    habe ich mich jetzt verständlich ausgedrückt ?


    Danke für eure hilfe im voraus ;)
    Nach einiger frustrierter Zeit des Codens auch mein Ansatz dazu. Etwas kniffliger als erwartet. Eigentlich geht es nur darum festzustellen, ob Großteile eines Pfades schon im TreeView drin sind und wenn nicht, dann eben alle Teile als neue, gestaffelte TreeNodes erstellen. Eigentlich.
    Mein Code geht davon aus, dass die Directories als DirectoyInfos eingebaut werden.
    Ich vermute mal, der klassische FolderBrowserDialog ist nicht ausreichend, richtig?
    Dateien
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hey :)

    das "PathToTreeView.zip" hat es geschafft und ich versuche es zu verstehen, da ich neu im vb .net bin und mir manche dinge noch recht schwierig erscheinen.

    1000 dank.

    als nächstes muß ich nun die dateien aus dem verzeichnis lesen und an die verzeichnisse dranhängen.

    ich habe da auch schon was gefunden....mal sehen ob es klappt ;)

    woeh schrieb:

    und ich versuche es zu verstehen, da ich neu im vb .net bin und mir manche dinge noch recht schwierig erscheinen.

    1000 dank.

    als nächstes muß ich nun die dateien aus dem verzeichnis lesen und an die verzeichnisse dranhängen.
    Seh ich anders.
    Als nächstes solltest du dir wirklich das Verständnis des Codes erarbeiten, und nich tschon mit was annerem anfangen.

    Beim Erarbeiten dieses Verständnisses wirst du allerlei neue Kenntnisse dir erwerben - Kenntnisse, die dir von anfang an nützen werden (oder eben fehlen) bei den Erweiterungen, die dir sonst noch vorschweben.

    Also stelle Fragen zu jeder Einzelnen Zeile, die du nicht verstehst (aber vlt nicht alle auf einmal).

    Es geht um
    diesen Code

    VB.NET-Quellcode

    1. Imports System.Runtime.CompilerServices
    2. Public Module Extensions
    3. Public Structure ApproachResult
    4. Public ReadOnly Nodes As TreeNodeCollection
    5. Public ReadOnly BestMatch As TreeNode
    6. Public ReadOnly StepsDone, InsertIndex As Integer
    7. Public ReadOnly Segments As IList(Of String)
    8. Public Sub New(Nodes As TreeNodeCollection, Node As TreeNode, Segments As IList(Of String), StepsDone As Integer, InsertIndex As Integer)
    9. Me.Nodes = Nodes
    10. Me.BestMatch = Node
    11. Me.Segments = Segments
    12. Me.StepsDone = StepsDone
    13. Me.InsertIndex = InsertIndex
    14. End Sub
    15. Public Sub InsertRest()
    16. If IsFullMatch Then Return
    17. Dim nodes = Me.Nodes.Insert(InsertIndex, Segments(StepsDone)).Nodes
    18. For i = StepsDone + 1 To Segments.Count - 1
    19. nodes = nodes.Add(Segments(i)).Nodes
    20. Next
    21. End Sub
    22. Public ReadOnly Property IsFullMatch() As Boolean
    23. Get
    24. Return InsertIndex < 0
    25. End Get
    26. End Property
    27. End Structure 'ApproachResult
    28. ''' <summary>
    29. ''' sucht in (sortierten) Nodes und SubNodes anhand eines Pfades nach dem bezeichneten Node.
    30. ''' Bei Nichtexistenz des ZielNode den übergeordneten, in den der ZielNode zu erstellen wäre
    31. ''' </summary>
    32. ''' <param name="PathSegments">Die Segmente des Pfades</param>
    33. ''' <returns>ein <seealso cref="ApproachResult"> ApproachResult</seealso>,
    34. ''' das den gefundenen Node enthält, und die Anzahl abgearbeiteter Segmente
    35. ''' </returns>
    36. <Extension()> _
    37. Public Function Approach(Nodes As TreeNodeCollection, PathSegments As IList(Of String)) As ApproachResult
    38. Dim Nd As TreeNode = Nothing, I As Integer
    39. For I = 0 To PathSegments.Count - 1
    40. Dim indx = Nodes.FindIndexByText(PathSegments(I))
    41. If indx < 0 Then Return New ApproachResult(Nodes, Nd, PathSegments, I, Not indx)
    42. Nd = Nodes(indx)
    43. Nodes = Nd.Nodes
    44. Next
    45. Return New ApproachResult(Nodes, Nd, PathSegments, I, -1)
    46. End Function
    47. ''' <summary>
    48. ''' sucht in (sortierten) Nodes nach einer Übereinstimmung mit txt. Wenn gefunden, dessen Index returnen. Wird ein Node angetroffen, dessen .Text grösser ist als txt, so ist die Suche auch beendet, denn aufgrund der Sortierung kann im folgenden kein Treffer mehr auftreten. Der Index dieses Auftretens bezeichnet dann die **EinfügePosition**, also wo ein matchender Node einzufügen wäre. Dieser Index wird bitweise negiert returnt, damit er von einem richtigen Treffer am Vorzeichen unterscheidbar ist, aber dennoch bei Bedarf ausgewertet werden kann - durch nochmaliges invertieren.
    49. ''' Die Konvention, die Einfügeposition als invertierten Index zu returnen, entspricht der Konvention von BinarySearch. Tatsächlich wäre hier auch eine BinarySearch angemessen, aber meine Faulheit verhinderte das
    50. ''' </summary>
    51. <Extension()> _
    52. Public Function FindIndexByText(nodes As TreeNodeCollection, txt As String) As Integer
    53. For i = 0 To nodes.Count - 1
    54. Select Case String.Compare(nodes(i).Text, txt, True)
    55. Case Is > 0 : Return Not i
    56. Case 0 : Return i
    57. Case Else
    58. End Select
    59. Next
    60. Return Not nodes.Count
    61. End Function
    62. <Extension()> _
    63. Public Function Approach(TV As TreeView, NodePath As String) As ApproachResult
    64. Return TV.Nodes.Approach(NodePath.Split(TV.PathSeparator(0)))
    65. End Function
    66. End Module
    - das ist wirklich von der Menge her überschaubar.

    (naja - also Verzeichnisse einlesen ist wirklich nur ein sehr kleiner nächster Schritt - zumal im gegebenen Upload ja auch vorgeturnt - unter btTest_Click())

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „ErfinderDesRades“ ()

    also was ich bräuchte wäre immer die aktuelle bzw letzte node, die er bei InsertRest() eingefügt hat.
    ich weiß nicht wie ich da rankomme...sonst müßte ich alles nochmal durchgehen wenn alles schon eingelesen ist und das finde ich umständlich.

    damit wäre mir schon geholfen.

    ich komme von vb6 und es macht mir immer noch kopfzerbrechen, das absolut alles objekte sind. selbst funktionen und subs...ich weiß, ich hätte früher damit anfangen sollen...aber es ist nun mal so ;)

    gruß

    woeh schrieb:

    also was ich bräuchte wäre immer die aktuelle bzw letzte node, die er bei InsertRest() eingefügt hat.
    Gute Idee!

    Und ist auch kein Problem, InsertNodes dahingehend umzustricken, dass es diesen zurückgibt:

    VB.NET-Quellcode

    1. Public Function InsertRest() As TreeNode
    2. If IsFullMatch Then Throw New InvalidOperationException("Es gibt keinen Rest zu inserten!")
    3. Dim nd = Me.Nodes.Insert(InsertIndex, Segments(StepsDone))
    4. For i = StepsDone + 1 To Segments.Count - 1
    5. nd = nd.Nodes.Add(Segments(i))
    6. Next
    7. Return nd
    8. End Function
    Siehst du: Vorher war es eine Sub, und hat nix returnt, jetzt returnt es den letzten zugefügten Treenode



    woeh schrieb:

    immer noch kopfzerbrechen, das absolut alles objekte sind. selbst funktionen und subs...
    Dassis Quatsch: funktionen und subs sind keine Objekte (sondern es sind Objekt-Member).

    Für einen Mini-Überflug, guggemol Grundlagen: Fachbegriffe

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    @woeh: Ggf. wäre es sinnvoll, beide Projekte zu prüfen, um verschiedene Herangehensweisen zu lernen. Allerdings kann ich mit folgendem nix anfangen:

    woeh schrieb:

    wenn er ein teilverzeichnis von einem verzeichnis existiert, wird es im pfad einfach aneinander gehangen und das führt zu einem fehler.

    Gib mal bitte ein konkretes Beispiel, welches zu einem Fehler führt, damit auch ich daraus lernen kann.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Jo, ich hab bislang mit deim Code auch kein Fehlverhalten feststellen können.
    Allerdings scheint er mir dennoch suboptimal, und ich verstehe ihn auch in einigen Punkten nicht.
    Etwa das hier:

    VB.NET-Quellcode

    1. For Each Directory In Directories
    2. Do Until SuccessfulAddDirectoryToTreeView(Directory)
    3. Dim ListOfPartialDirectories = GetListOfPartialDirectories(Directory, "")
    4. TreeView1.Nodes.Add(ListOfPartialDirectories(0))
    5. Loop
    6. Next
    Dass du alle Directories mit foreach durchgehst ist logisch.
    Aber jedes einzelne scheint noch in eine "Probier-Do-Loop" geschickt zu werden, wobei der Input überhaupt nicht variiert wird - wird ja immer dassselbe Directory hineingegeben - was hat das für eine Bewandniss?
    also....mein code machte folgendes...
    mit ner api-funktion wurden verzeichnisse eingelesen und darauf geprüft ob mehr als 1 mp3-datei in den alben-verzeichnissen liegt. dann wurde das ganze per eben dieser funktion an das treeview übergeben.
    zm testen hatte ich mir einige verzeichnisse auf eine andere partion kopiert und das lief auch alles.
    da alles soweit lief hatte ich es dann mit der ganzen sammlung probiert. das sind über 100000 mp3-dateien.

    und aben dort gab es den fehler in Nodes.Fullpath.
    er hat einfach folgendes verzeichnis:
    G:\Eigene Musik\Dark\After Forever\After Forever - Decipher - The Album - The Sessions
    an folgendes verzeichnis
    G:\Eigene Musik\Dark\After Forever\After Forever - Decipher
    drangehangen.

    als ich dann den pfad mittels IO.Path.GetDirectoryName() gegencheckte kam es halt zu einem fehler
    als ich nodes.fullpath ausgelesen hatte.

    weiß nicht, ob das jetzt verständlich war....

    und...ich weiß sicherlich, das man einen sub zu einer funktion umschreiben kann.
    das projekt existiert im vb6 bereits zu 4/5....aber wegen der einschränkungen habe ich jetzt eben mit vs2015 angefangen.

    eigentlich brauche ich noch die letzte node aus Nodes.Approach...
    diese nodes verweisen eben auf das verzeichnis auf der platte...
    es werde ja noch dateien an die nodes gehangen.

    ich habe gerade mal geschaut...

    VB.NET-Quellcode

    1. Dim P As Long
    2. Dim Dir As String
    3. Dim sDir() As String
    4. Dim nNode As TreeNode
    5. dirWork = DirList
    6. If ArrayIsEmpty(DirList) = False Then
    7. For P = 0 To UBound(DirList)
    8. Dir = DirList(P)
    9. sDir = Split(Dir, "\"c)
    10. With frm.tvSource.Nodes.Approach(sDir)
    11. nNode = .InsertRest()
    12. End With
    13. Next P
    14. End If


    das klappt soweit ganz gut....aller dings wenn er bei
    .InsertRest nothing zurückgibt ist das natürlich auch mist, da ich wieder nicht an die node komme.

    ich brauche diese unbedingt, da die node eben auf ein verzeichnis verweist...

    sehe ich folgendes richtig ?
    wenn er bei
    With frm.tvSource.Nodes.Approach(sDir)
    die node nicht hinzufügt, wird das bei
    .InsertRest()
    gemacht.
    ich habe eben einfach ne public node deklariert und laße sie mir bei der funktion
    Public Function Approach(Nodes As TreeNodeCollection, ...
    am ende übergeben.

    wenn das der fall ist, das sie ebtweder nur bei der ersten funktion und wenn nicht bei der zweiten funktion übergen wird, habe ich es geschafft und alles ist gut.

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „woeh“ ()

    woeh schrieb:

    aller dings wenn er bei
    .InsertRest nothing zurückgibt ist das natürlich auch mist, da ich wieder nicht an die node komme.
    Dochdoch - kein Problem.
    Du musst nur bischen den Code angucken, nachdenken, was da steht, und dann kommst du drauf, wie du auf andere Weise an den Node kommst.
    Ausserdem gibt InsertRest gar nicht Nothing zurück (habich geändert).

    Aber nur immer andere für sich programmieren lassen, ohne selbst nachzudenken, da verlieren die recht bald die Lust.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    so....ich habe es geschafft..

    VB.NET-Quellcode

    1. Private Sub PathToTreeView(DirList() As String,
    2. frm As frmMain)
    3. Dim P As Long, X As Long
    4. Dim Dir As String, Path As String, R$
    5. Dim sDir() As String, nDir() As String, mDir() As String
    6. Dim nNode As TreeNode, mNode As TreeNode
    7. dirWork = DirList
    8. Path = frm.cbDir.Text
    9. mDir = Split(Path, "\"c)
    10. If ArrayIsEmpty(DirList) = False Then
    11. frm.tvSource.Nodes.Add(Path)
    12. For P = 0 To UBound(DirList)
    13. Dir = DirList(P)
    14. sDir = Split(Dir, "\"c)
    15. ReDim nDir(0)
    16. nDir(0) = Path
    17. For X = (UBound(mDir) + 1) To UBound(sDir)
    18. Call AddToArray(nDir, sDir(X))
    19. Next X
    20. With frm.tvSource.Nodes.Approach(nDir)
    21. nNode = .InsertRest()
    22. If nNode IsNot Nothing Then
    23. Call InsertFiles(nNode)
    24. Else
    25. If rNode IsNot Nothing Then
    26. Call InsertFiles(rNode)
    27. End If
    28. End If
    29. End With
    30. Next P
    31. End If
    32. End Sub
    33. Private Sub InsertFiles(nNode As TreeNode)
    34. Dim Path As String
    35. Path = nNode.FullPath
    36. For Each file In IO.Directory.GetFiles(Path)
    37. If IO.Path.GetExtension(file) = ".mp3" Then
    38. nNode.Nodes.Add(IO.Path.GetFileName(file))
    39. End If
    40. Next
    41. End Sub


    das erfüllt seinen zweck und funktioniert super !

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „woeh“ ()

    woeh schrieb:

    VB.NET-Quellcode

    1. If nNode IsNot Nothing Then
    2. Call InsertFiles(nNode)
    3. Else
    4. If rNode IsNot Nothing Then
    5. Call InsertFiles(rNode)
    6. End If
    7. End If
    What :?:
    Geht doch kürzer:

    VB.NET-Quellcode

    1. If nNode IsNot Nothing Then
    2. Call InsertFiles(nNode)
    3. End If

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ich habe das getestet und durch mein archiv laufen lassen...das sind tausende verzeichnisse und dateien....es funktioniert! ich habe es mehrmals getestet.

    VB.NET-Quellcode

    1. If nNode IsNot Nothing Then
    2. Call InsertFiles(nNode)
    3. End If


    das reicht nicht...weil eben die funktion
    Public Function Approach(Nodes As TreeNodeCollection,
    PathSegments As IList(Of String)) As ApproachResult
    selber nodes adden kann und wenn die funktion nNode = .InsertRest() nothing ergibt wurde die node eben durch Approach(Nodes As TreeNodeCollection, .... geaddet.

    deshalb

    VB.NET-Quellcode

    1. Public Module clsExtensions
    2. Public rNode As TreeNode
    3. Public Function Approach(Nodes As TreeNodeCollection,
    4. PathSegments As IList(Of String)) As ApproachResult
    5. Return New ApproachResult(Nodes, Nd, PathSegments, I, -1)
    6. rNode = Nd

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „woeh“ ()

    alea iacta est - pro EDR (seine Erfahrung siegt, das sollte niemanden überraschen :) )
    Trotzdem werd ich die Finger nicht still halten und zumindest für mich meine Lösung weiterbasteln. ;)
    @ErfinderDesRades: Bezüglich Deines Posts: Das war für mich ne Zwickmühle aus DRY und KISS. Wenn kein passender Knoten gefunden wurde, wurde dem TV ein ganz neuer Node hinzugefügt und dann die SuccessfulAddDirectoryToTreeView nochmal aufgerufen, die dann auf jeden Fall True zurückgeliefert hätte.
    Inzwischen hab ich alles in ne Klasse gepackt und umgestaltet. Für den Fall, dass jemand interessiert sein sollte. Oder wär das dann schon off-topic?

    EDIT: Dass in diesem Fall zu KISS natürlich auch Split("\"c) gehört, wie es EDR schon die ganze Zeit verwendet, ist mir jetzt erst bei Motorradfrischluft gekommen.
    Dateien
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Hallo :)

    ich weiß, der thread ist etwas älter...aber ich habe da mal noch ne frage.
    ich arbeite mit der damaligen lösung "TreeviewFromFile02.zip".
    mit deren hilfe ich ein preview erstellen laße. so weit, so gut.

    was mir allerdings kopfschmerzen bereitet ist folgendes:
    ich füge der Node ein Image hinzu...funktioniert.
    ich füge der Node ein ToolTip hinzu...funktioniert nur wenn die anzahl der der unterknoten >1 ist

    folgendes funktioniert

    (der Tooltip stimmt schon, weil das der original dateipfad ist)

    folgendes funktioniert nicht


    ist das problem bekannt oder woran liegt das ? oder was könnte das sein ?

    vielen dank im voraus für eure antwort & danke fürs lesen :P
    Bilder
    • Aufnahme2.jpg

      78,07 kB, 547×331, 843 mal angesehen
    • Aufnahme3.jpg

      81,54 kB, 547×331, 820 mal angesehen
    Hallo :)

    ich poste mal die routine, bei der der tooltip eingefügt wird.
    vielleichts hilfts ja und jmd sagt etwas auf meine anfrage.

    VB.NET-Quellcode

    1. tv.Nodes.Clear()
    2. For p = 0 To previewFiles.Count - 1
    3. orgFile = previewFiles(p).ToString
    4. file = orgFile
    5. Do
    6. With tv.Nodes.Approach(file.Split("\"c))
    7. node = .InsertRest()
    8. If node IsNot Nothing Then
    9. node.ImageIndex = 1
    10. node.SelectedImageIndex = 1
    11. node.ToolTipText = previewOrgFiles(p).ToString
    12. nIndex = 0
    13. Exit Do
    14. Else
    15. If Not mainform.chkFilePerTagRenameIfExist.Checked Then
    16. Exit Do
    17. End If
    18. nIndex += 1
    19. fileName = IO.Path.GetFileNameWithoutExtension(orgFile)
    20. fileExt = IO.Path.GetExtension(orgFile)
    21. filePath = cGeneral.GetPath(IO.Path.GetDirectoryName(orgFile))
    22. str = nIndex.ToString
    23. If str.Length = 1 Then str = "0" & str
    24. file = filePath & fileName & " (" & str & ")" & fileExt
    25. End If
    26. End With
    27. Loop
    28. Next p