Keine Strings in die File-Listbox!

    • VB.NET

    Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

      Keine Strings in die File-Listbox!

      Recht häufig stoße ich auf Posts, wo Dateinamen in Listboxen gestopft werden, und will man die Datei dann kopieren, dann steht der Dateipfad nicht zur Verfügung und vergleichbares Zeug.

      Listbox ist nicht dazu da, dumme Strings aufzunehmen, sie kann ganze FileInfos aufnehmen, und der DateiPfad ("Fullname") ist nur eine der mannigfachen Datei-Information, die FileInfo bereitstellt.

      Also: Vergesst Directory.GetFiles(), und nehmt stattdessen DirectoryInfo.GetFiles() !!
      Und vergesst auch den My.Computer.FileSystem - Namespace, denn auch sowas:

      VB.NET-Quellcode

      1. For Each datei In My.Computer.FileSystem.GetFiles(Pfad, FileIO.SearchOption.SearchTopLevelOnly, directoryName)
      liefert keine FileInfos, sondern nur dumme Strings.

      Und trennt Daten von Controls.
      Also füllt nicht die .GetFiles() direkt in die Listbox, sondern füllt eine List(Of FileInfo) damit ab, und bindet die Listbox daran.

      Listbox hat die erfreuliche Property .DisplayMember, mit der man angeben kann, welche der 15 Properties eines FileInfos angezeigt werden soll.
      Hier habe ich eine App gebastelt, mit der man den DisplayMember sogar umschalten kann.
      Das Umschalten erfolgt über eine Combobox cmbDisplayMember, die an ein String-Array gebunden ist, welche schomal 7 der 15 FileInfo-Properties bezeichnen.

      Damit ist hoffentlich bewiesen, dass eine mit FileInfos befüllte Listbox wesentlich mächtiger ist, als wenn man nur dumme Strings einfüllt.

      Im cmbDisplayMember_SelectedIndexChanged() wird der selektierte DisplayMember nicht aus der Combo geholt, sondern aus dem zugrundeliegenden String-Array.
      Denn letzteres ist typisiert, während ich bei Zugriff per cmbDisplayMember.SelectedItem hätte eine Typumwandlung durchführen müssen.

      Das gleiche Prinzip bei btShowCreationTime_Click(): das aktuell angewählte FileInfo wird nicht aus der Listbox gepuhlt, sondern dem FileInfo-Array entnommen - ebenfalls ohne Typumwandlung.
      Mit diesem FileInfo könnte ich jetzt alles mögliche machen: kopieren, löschen, verschieben - aber im Sample zeige ich nur die .CreationTime an.

      Also: Beim Proggen immer schön sauber bleiben! ;)

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class frmFileInfoToListbox
      3. Private _Files As FileInfo()
      4. Private _DisplayMembers As String() = "Name Fullname Extension Length Exists Attributes CreationTime".Split
      5. Private Sub frmFileInfoToListbox_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
      6. cmbDisplayMember.DataSource = _DisplayMembers
      7. dlgFolder.SelectedPath = Path.GetFullPath("..\..\")
      8. Reload()
      9. End Sub
      10. Private Sub cmbDisplayMember_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles cmbDisplayMember.SelectedIndexChanged
      11. lstFiles.DisplayMember = _DisplayMembers(cmbDisplayMember.SelectedIndex)
      12. End Sub
      13. Private Sub btFolder_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btFolder.Click
      14. If dlgFolder.ShowDialog = Windows.Forms.DialogResult.OK Then Reload()
      15. End Sub
      16. Private Sub btShowCreationTime_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btShowCreationTime.Click
      17. MessageBox.Show(_Files(lstFiles.SelectedIndex).CreationTime.ToString)
      18. End Sub
      19. Private Sub Reload()
      20. Dim di = New DirectoryInfo(dlgFolder.SelectedPath)
      21. _Files = di.GetFiles("*.*", SearchOption.AllDirectories)
      22. lstFiles.DataSource = _Files
      23. End Sub
      24. End Class


      Dateien

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

      Erweiterung - PictureViewer

      Habe jetzt mal 2 Forms drangemacht, die intensiver Databinding verwenden.

      Erstmal eine Zwischenstufe, bei der statt eines Arrays eine BindingList(Of FileInfo) als DataSource verwendet wird.

      Dann die "Endstufe", bei der im Datenfenster die Klasse "System.IO.FileInfo" als ObjectDatasource eingerichtet ist (im Datenfenster auf "Datenquelle hinzufügen" klicksen, und die FileInfo-Klasse in der mscorlib-Dll suchen).

      Alle Bindings sind im Designer eingerichtet, nämlich Picturebox.ImageLocation (!!) und Listbox.Datasource. Dadurch wird der eigentliche Code wesentlich knapper, und kümmert sich wirklich nur um die erforderlichen Sachen.

      Das macht ihn so klar, dass eiglich keine weitere Erläuterung des Codes nötig erscheint:

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class frmDataboundPictureViewer
      3. Private _Extensions As String() = ".gif;.jpg;.jpeg;.png;.bmp;.dib;.tif;.wmf;.ras;.eps;.pcx;.pcd;.tga".Split(";"c)
      4. Private Sub frmPictureViewer_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
      5. dlgFolder.SelectedPath = Path.GetFullPath("..\..\Pictures\")
      6. Reload()
      7. End Sub
      8. Private Sub btFolder_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btFolder.Click
      9. If dlgFolder.ShowDialog <> Windows.Forms.DialogResult.OK Then Return
      10. Reload()
      11. End Sub
      12. Private Sub btRemove_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btRemove.Click
      13. DirectCast(FileInfoBindingSource.Current, FileInfo).Delete()
      14. FileInfoBindingSource.RemoveCurrent()
      15. End Sub
      16. Private Sub Reload()
      17. Dim di = New DirectoryInfo(dlgFolder.SelectedPath)
      18. Dim images = From fileInfo In di.GetFiles("*.*", SearchOption.AllDirectories) Where _Extensions.Contains(fileInfo.Extension)
      19. FileInfoBindingSource.DataSource = images
      20. End Sub
      21. Private Sub FileInfoBindingSource_CurrentChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FileInfoBindingSource.CurrentChanged
      22. btRemove.Enabled = FileInfoBindingSource.Current IsNot Nothing
      23. End Sub
      24. End Class



      Die Anwendung kann einen Ordner anwählen, und bietet alle enthaltenen Bilder zur Auswahl. Und es gibt einen Button zum Löschen eines Bildes - das ist oft ja ein Problem, wenn eine BildDatei gelöscht werden soll, während sie angezeigt wird.
      Die Lösung des Problem besteht darin, dass der Picturebox kein Image zugewiesen wird, sondern stattdessen ist die ImageLocation gebunden.
      Dadurch kümmert sich die PB selbst um das Laden der Datei, und das handelt sie offensichtlich so, dass nach dem Lade-Vorgang keine Sperre der Datei besteht :D
      Dateien

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

      Den PictureViewer habich heut nochmal neu programmiert, damit ihr dabei zugucken könnt.
      Weil das Databinding ist doch recht trickreich, und wenn man nur den Code sichtet, kommt man kaum dahinter, wie man das macht, weils ist halt im Designer gemacht:
      DirectLink
      Die neue Source ist bisserl einfacher, und ist hier eingestellt.

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

      Cooles Tutorial, aber beim Video muss ich sagen, dass es etwas sehr lange ist, du verbringst, bevor es zum Coden geht, 6 Minuten mit Layout der Form und Erstellung der Datasource, das lässt sich sicher auch auf 2 Minuten verkürzen ;).
      Ähm - dassis aber grad der Sinn vom Video: die Arbeit mit den Designern und Assistenten zu zeigen - nicht das Hinschreiben von Code in den Editor.
      Letzteres braucht kein Video, weil einfach nur den Code (besseren sogar!) kannste besser direkt in post#2 nachlesen und sogar downloaden.

      Aber wie ein SplitContainer tickt, wie man Docking anwendet, wo das Datenfenster ist, wie man FileInfo als DatenQuelle einrichtet, wie eine Listbox da anhängen und wie die Picturebox - das sind die Sachen, die das Video zeigt, denn im Code später ist das nicht mehr zu sehen.
      Und nebenbei auch Sorgfalt bei der Vergabe von Namen, dass die Dinge sofort einen treffenden Namen bekommen, weil "der Name ist Programm".

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