The problem, as you realised, is that the filename only is not enough information to delete a file. You need the whole path to the file as well. So you need some way of storing the whole path but only showing the filename. This is also important because there might be two (or more) files with same name in separate directories.
A ListBox can have its Datasource
property set to show items from "an object that implements the IList or IListSource interfaces, such as a DataSet or an Array."
Then you set the DisplayMember
and ValueMember
properties to tell it what to display and what to give as the value.
For example, I made up a class named "FileItem" which has properties for the full filename and for whatever you want to display it as, filled a list with instances of "FileItem", and told ListBox1 to display it:
Imports System.IO
Public Class Form1
Class FileItem
Property FullName As String
Property DisplayedName As String
Public Sub New(filename As String)
Me.FullName = filename
Me.DisplayedName = Path.GetFileNameWithoutExtension(filename)
End Sub
End Class
Private Sub PopulateDeletionList(dir As String, filter As String)
Dim files = Directory.EnumerateFiles(dir, filter, SearchOption.AllDirectories)
Dim fileNames = files.Select(Function(s) New FileItem(s)).ToList()
Dim bs As New BindingSource With {.DataSource = fileNames}
ListBox1.DataSource = bs
ListBox1.DisplayMember = "DisplayedName"
ListBox1.ValueMember = "FullName"
End Sub
Private Sub ListBox1_Click(sender As Object, e As EventArgs) Handles ListBox1.Click
Dim lb = DirectCast(sender, ListBox)
Dim sel = lb.SelectedIndex
If sel >= 0 Then
Dim fileToDelete = CStr(lb.SelectedValue)
Dim choice = MessageBox.Show("Do you really want to delete " & fileToDelete, "Confirm file delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If choice = DialogResult.Yes Then
Try
File.Delete(fileToDelete)
lb.DataSource.RemoveAt(sel)
Catch ex As Exception
MessageBox.Show("Could not delete " & fileToDelete & " because " & ex.Message)
End Try
End If
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PopulateDeletionList("C:\temp", "*.txt")
End Sub
End Class
Edited I had forgotten to delete the item from the ListBox. To do that, it needs to be tied to the DataSource through a BindingSource.
Extra feature Seeing as there could be more than one file with the same name, you might want to add a tooltip to the listbox items so that you can see which directory it is in. See how to add tooltips on winform list box items for an implementation which needs only minor adjustments to work, such as:
Dim toolTip As ToolTip = New ToolTip()
' ...
Private Sub ListBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseMove
Dim lb = DirectCast(sender, ListBox)
Dim index As Integer = lb.IndexFromPoint(e.Location)
If (index >= 0 AndAlso index < ListBox1.Items.Count) Then
Dim desiredTooltip = DirectCast(lb.Items(index), FileItem).FullName
If (toolTip.GetToolTip(lb) <> desiredTooltip) Then
toolTip.SetToolTip(lb, desiredTooltip)
End If
End If
End Sub