Search code examples
vb.netlistboxfilenamesdelimiteralphabetical-sort

How to sort a listbox full of files with (3 category) dash delimited names via radio buttons in VB.Net 2017?


So I am building my first program in quite some time and have bashed my way through most of it successfully. Now I am running into a problem and need to ask some advice.

Description: I have a directory of notepad text (of lyrics and chord arrangements) files with titles formatted as follows. Songtitle-Artist-Key.txt First I browse for their directory which populates a listbox. Then after I select a song from said listbox, it populates 1 of 3 textboxes depending upon which textbox I assign it to via command buttons (some songs have up to 3 pages.) All of this works fine so far. (Future quest would be to automatically put a song with 2 or 3 pages into each respective textbox when the first one is clicked.)

Goal: I have 3 radio buttons labeled Title, Artist, and Key within a group control. These are meant to be used to sort the listbox by their respective names, Title, Artist, and Key.

Questions: Can I sort this listbox according to delimited category, or do I need to have 3 separate listboxes (and how would I keep them synchronized), or do I need to have some sort of data element involved? Any suggestions, thoughts, examples, or ideas welcome!

Edit: This says exactly what I want it to say, having read the how to ask page and having searched for over a full day, I am reopening this question.

Thanks, DiggDuggster


Solution

  • If you are working with an older version of vb you will not be able to use interpolated strings ($). Change to String.Format. Other explanation is in code comments.

    Public Class frmSortedList
        Private lstSongs As New List(Of Song)
        Public SortOrder As Integer = 0
        Private Sub frmSortedList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim lstFileName As New List(Of String)
            lstFileName.Add("Star Spangled Banner-Francis Scott Keyes-G.txt")
            lstFileName.Add("Jailhouse Rock-Elvis Presley-F.txt")
            lstFileName.Add("Macho Insecurity-Dead Kennedys-G.txt")
            lstFileName.Add("(We Are) The Road Crew-Motorhead-F.txt")
            lstFileName.Add("Moonlight Drive-The Doors-B.txt")
            lstFileName.Add("While My Guitar Gently Weeps-The Beatles-B.txt")
            lstFileName.Add("Waffle-Sevendust-G.txt")
            lstFileName.Add("Don't Take Your Guns To Town-Johnny Cash-G.txt")
            lstFileName.Add("Where Eagles Dare-Iron Maiden-B.txt")
            lstFileName.Add("London Calling-The Clash-F.txt")
            'your list will come from your Directory
            'loop through you list of file names (or an array of file names
            'call the constructor of Song passing the file name
            'add the Song object to the list
            For Each file As String In lstFileName
                Dim s As New Song(file)
                lstSongs.Add(s)
            Next
            'The ListBox will call .ToString on the objects you add
            'to determine what to display
            ListBox1.DataSource = lstSongs
            ListBox1.ValueMember = "FileName"
            'To access any of the properties of the items in the ListBox
            'Cast the object stored in the ListBox back to song
            Dim item As Song = CType(ListBox1.SelectedItem, Song)
            Debug.Print($"Title: {item.Title}, Artist: {item.Artist}, Key: {item.MusicKey}")
            'You can set the value property to any property of Song
            Dim thefile As String = CStr(ListBox1.SelectedValue)
            Debug.Print(thefile)
        End Sub
        Private Sub btnArtist_Click(sender As Object, e As EventArgs) Handles btnArtist.Click
            'A little link code to sort the list
            SortOrder = 1
            Dim lstArtists As List(Of Song) = lstSongs.OrderBy(Function(s) s.Artist).ToList
            ListBox1.DataSource = Nothing
            ListBox1.DataSource = lstArtists
            ListBox1.ValueMember = "FileName"
        End Sub
    
        Private Sub btnTitle_Click(sender As Object, e As EventArgs) Handles btnTitle.Click
            SortOrder = 0
            Dim lstTitle As List(Of Song) = lstSongs.OrderBy(Function(s) s.Title).ToList
            ListBox1.DataSource = Nothing
            ListBox1.DataSource = lstTitle
            ListBox1.ValueMember = "FileName"
        End Sub
    
        Private Sub btnKey_Click(sender As Object, e As EventArgs) Handles btnKey.Click
            SortOrder = 2
            Dim lstKey As List(Of Song) = lstSongs.OrderBy(Function(s) s.MusicKey).ToList
            ListBox1.DataSource = Nothing
            ListBox1.DataSource = lstKey
            ListBox1.ValueMember = "FileName"
        End Sub
    End Class
    Public Class Song
        Public ReadOnly Property Title As String
        Public ReadOnly Property Artist As String
        Public ReadOnly Property MusicKey As String
        Public ReadOnly Property ShortFileName As String
        Public Property FileName As String
        Public Sub New(file As String)
            FileName = file 'the full file name that was passed to the constructor
            Dim index As Integer = file.IndexOf(".") 'Find where the extension starts
            ShortFileName = file.Remove(index) 'Get rid of .txt
            Dim parts As String() = ShortFileName.Split("-"c) 'Split returns and array
            Title = parts(0)
            Artist = parts(1)
            MusicKey = parts(2)
        End Sub
        Public Overrides Function ToString() As String
            'The ListBox calls .ToString on the objects you added
            'You can return any property of combination of properties
            'you want to display
            'if you don't override you will get the fully qualified name of the object Argh!
            Select Case frmSortedList.SortOrder
                Case 0
                    Return ShortFileName
                Case 1 'Artist
                    Return $"{Artist} - {Title} -  {MusicKey}"
                Case 2 'key
                    Return $"{MusicKey} - {Title} - {Artist}"
                Case Else
                    Return ShortFileName
            End Select
        End Function
    End Class