Devin
Devin

Reputation: 277

VB.Net error checking if dictionary inside list contains string

I'm creating an application where I have different libraries, books and non-book media stored in dictionaries and displayed in listboxes. The user can add and remove additional dictionaries for any of these elements.

I have a listbox for "Books at Current library" and "Non-Book Media at Current Library" Which will display the media that is linked to the specific library that is highlighted in the listbox. And the user can freely add and remove different media to the library.

I'm having an issue where if I try to add a book to my current EquippedLibrary it errors out when I add a duplicate.

Screenshots of the two forms:

frmManager: https://prnt.sc/mnd8qf

frmAssociationScreen: https://prnt.sc/mnd8sh

Entire code: https://pastebin.com/5yHTuTXU

I tried using the following Sub However the .Contains keyword does not work due to not being able to convert from Integer to String

Private Sub btnAddBook_Click(sender As Object, e As EventArgs) Handles btnAddBook.Click
        If frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).strLibraryName.Contains(lstBookCurrLib.SelectedIndex) Then
         'Do nothing
        Else
        frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Add(frmManager.Books.Keys(lstAllBooks.SelectedIndex), frmManager.Books.Values(lstAllBooks.SelectedIndex))
            lstBookCurrLib.Items.Add(lstAllBooks.SelectedItem)
        End If
    End Sub

frmAssociationScreen

Public Class frmAssociationScreen

    Private Sub frmAssociationScreen_Load(sender As Object, e As EventArgs) Handles Me.Load

        lstAllLibraries.Items.Clear()

        For Each library In frmManager.Libraries
            lstAllLibraries.Items.Add(library.Value & " --- " & library.Key)
        Next

        For Each book In frmManager.Books
            lstAllBooks.Items.Add(book.Value & " --- " & book.Key)
        Next

        For Each nonBook In frmManager.nonBookMedia
            lstAllMedia.Items.Add(nonBook.Value & " --- " & nonBook.Key)
        Next

        ' construct equipped library and define the library names
        frmManager.EquippedLibrary = New List(Of frmManager.LibraryWithMedia)

    populateEquippedLibNames()

End Sub



Sub populateEquippedLibNames()

        Dim counter As Integer
        Dim tmpSingleLib As frmManager.LibraryWithMedia

        For counter = 0 To frmManager.Libraries.Count - 1
            tmpSingleLib = New frmManager.LibraryWithMedia(frmManager.Libraries.Values(counter))
            frmManager.EquippedLibrary.Add(tmpSingleLib)
            tmpSingleLib = Nothing
        Next

    End Sub

Private Sub btnAddBook_Click(sender As Object, e As EventArgs) Handles btnAddBook.Click
    If frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).strLibraryName.Contains(lstBookCurrLib.SelectedIndex) Then
        'Do nothing
    Else
            'If lstBookCurrLib.Contains(frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Add(frmManager.Books.Keys(lstAllBooks.SelectedIndex), frmManager.Books.Values(lstAllBooks.SelectedIndex))) Then
            frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Add(frmManager.Books.Keys(lstAllBooks.SelectedIndex), frmManager.Books.Values(lstAllBooks.SelectedIndex))
            lstBookCurrLib.Items.Add(lstAllBooks.SelectedItem)
    End If
End Sub

        Private Sub btnRemoveBook_Click(sender As Object, e As EventArgs) Handles btnRemoveBook.Click
            frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Remove(frmManager.Books.Keys(lstAllBooks.SelectedIndex))
            lstBookCurrLib.Items.Remove(lstBookCurrLib.SelectedItem)
        End Sub

        Private Sub lstAllLibraries_SelectedIndexChanged(sender As Object, e As EventArgs) Handles lstAllLibraries.SelectedIndexChanged

            lstBookCurrLib.Items.Clear()
            lstMediaCurrLib.Items.Clear()

            If frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Count > 0 Then
                For counter = 0 To frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Count - 1
                    lstBookCurrLib.Items.Add(frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Values(counter) & " --- " & frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).dicBooks.Keys(counter))
                Next
            End If

            If frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).nonBookMedia.Count > 0 Then
                For counter = 0 To frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).nonBookMedia.Count - 1
                    lstMediaCurrLib.Items.Add(frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).nonBookMedia.Values(counter) & " --- " & frmManager.EquippedLibrary(lstAllLibraries.SelectedIndex).nonBookMedia.Keys(counter))
                Next
            End If

    End Sub

    Private Sub frmAssociationScreen_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
        frmManager.Close()
    End Sub

End Class

frmManager

Public Class frmManager

    Public Libraries As New Dictionary(Of String, String)
    Public Books As New Dictionary(Of String, String)
    Public nonBookMedia As New Dictionary(Of String, String)

    Public EquippedLibrary As New List(Of LibraryWithMedia)

    Structure LibraryWithMedia

        Dim strLibraryName As String
        Dim dicBooks As Dictionary(Of String, String)
        Dim nonBookMedia As Dictionary(Of String, String)

        Sub New(ByVal LibName As String)

            strLibraryName = LibName
            dicBooks = New Dictionary(Of String, String)
            nonBookMedia = New Dictionary(Of String, String)

        End Sub

    End Structure

    Private Sub frmManager_Load(sender As Object, e As EventArgs) Handles Me.Load

        Libraries.Add("SVSU", "Zahnow Library")
        Libraries.Add("BR", "Fleschner Memorial Library")
        Libraries.Add("SDJ", "Scott D. James Technical Repository")

        Books.Add("104", "Data Structures for Fun and Profit")
        Books.Add("103", "Doing More With Less - Naval Lint Art")
        Books.Add("102", "Interpretive Klingon Poetry")
        Books.Add("105", "Programming with the Bidgoli")
        Books.Add("101", "Zen and the Art of Appliance Wiring")

        nonBookMedia.Add("201", "CD - IEEE Computer: the Hits")
        nonBookMedia.Add("203", "DVD - Databases and You: the Video Experience")
        nonBookMedia.Add("202", "DVD - The Pirates of Silicon Valley")

        populatelstLibrary()
        populatelstBooks()
        populatelstBookMedia()

    End Sub

    Sub populatelstLibrary()

        lstLibraries.Items.Clear()

        For Each library In Libraries
            lstLibraries.Items.Add(library.Value & " --- " & library.Key)
        Next

    End Sub

Upvotes: 0

Views: 75

Answers (1)

Visual Vincent
Visual Vincent

Reputation: 18310

In its current state your code is rather messy as it contains both a lot of duplicated/similar parts as well as some very long lines. This, in general, is a maintenance nightmare.

This answer turned out quite long as there was much to explain and refactor, however, these changes make your code much easier to understand and work with so that you can change/adapt it further in the future.

If you have any questions, don't hesitate to ask!

Object-Oriented Programming

Object-Oriented Programming (OOP) is all about working with objects (classes, structures, etc.) in order to allow a much greater level of Separation of Concerns (SoC). By separating your code into, not only objects but also files, you allow more of the related bits of code to handle themselves. This is good as it makes it easier for us as developers to both inspect, debug and troubleshoot our code.

Your code can be separated into multiple objects in order to make it both more abstract and self-contained, which will make the next problem you bump into (likely) much easier to solve (so you don't have to turn to Stack Overflow every time :).


1. A module for your "global" variables

First off I think you should declare a module for your "global" variables (those being the variables that you refer to in both forms). This will allow you to move your lists and dictionaries out of frmManager.

Right-click your project in the Solution Explorer and go to Add > New Item..., then select Module and give it a name of your choice (I named it GlobalMembers). We shall move the variables there in a just a while...

Friend Module GlobalMembers

End Module


2. The Library class

Now, you should create a class holding all the information of a single library - this includes which books and media it contains. This helps you both more easily get all the information you need from a specific library, as well as simply get and modify its selection of different media. Thanks to this the EquippedLibrary list is now useless and can therefore be removed.

The class will contain five properties:

  • Code - The library code (e.g. SVSU).
  • Name - The name of the library (e.g. Zahnow Library).
  • DisplayName - How the library will be displayed in, for example, a ListBox.
  • Books - A HashSet(Of String) of all book IDs available in the library.
  • Media - A HashSet(Of String) of non-book media IDs available in the library.

A HashSet is used as it provides a hash-based lookup mechanism (similar to the Dictionary) and therefore it doesn't allow duplicates. It is basically a list without duplicates.

The reason I'm using this is because it will only hold the IDs of the books and other media. This is all we need since we can then use each ID to lookup the respective book or media in the global Books and NonBookMedia dictionaries.

This saves us both from storing the books twice and potentially causing our lists to go completely out of sync.

Now, to add a class, right-click your project in the Solution Explorer, goto Add > New Item... and select Class.

Public Class Library

    ''' <summary>
    ''' Gets or sets the library code. This must correspond to a key in the GlobalMembers.Libraries dictionary!
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Code As String

    ''' <summary>
    ''' Gets or sets the name of the library.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Name As String

    ''' <summary>
    ''' Gets or sets the list of books (IDs) contained within the library. 
    ''' Each value should correspond to a key in the GlobalMembers.Books dictionary.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Books As New HashSet(Of String)

    ''' <summary>
    ''' Gets or sets the list of non-book media (IDs) contained within the library. 
    ''' Each value should correspond to a key in the GlobalMembers.NonBookMedia dictionary.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property NonBookMedia As New HashSet(Of String)

    ''' <summary>
    ''' Gets the display name of the library.
    ''' </summary>
    ''' <remarks></remarks>
    Public ReadOnly Property DisplayName As String
        Get
            'The text to display in for example a ListBox.
            Return Me.Name & " --- " & Me.Code
        End Get
    End Property

    ''' <summary>
    ''' Initializes a new instance of the Library class.
    ''' </summary>
    ''' <param name="Name">The name of the library.</param>
    ''' <param name="Code">The library code. This must correspond to a key in the GlobalMembers.Libraries dictionary!</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Name As String, ByVal Code As String)
        'Constructor. Called whenever we write "New Library(...)".
        Me.Name = Name
        Me.Code = Code
    End Sub
End Class

Note that the XML comments in the code (<summary></summary> etc.) helps you by providing a description displayed by IntelliSense as you type your code.

IntelliSense example


3. The Book and Media classes

Now we're going to create a class for our books and non-book media. It's not much different from what we've done so far.

The Book class will contain:

  • ID - The book's ID (e.g. 102).
  • Name - The book's name (e.g. Interpretive Klingon Poetry).
  • DisplayName - How the book will be displayed in, for example, a ListBox.

The Media class will contain:

  • ID - (same as above)
  • Name - (same as above)
  • DisplayName - (same as above)
  • Type - What type of media this is (e.g. CD, DVD, etc.).

As before, start by adding a new Class file to your project for each of the two.

NOTE:
Normally you might want to use polymorphism (i.e. inheritance) for the Book and Media classes, but I'm not sure how much you know about OOP and I don't want to make this answer too long, so I've made them two separate classes for now.

Book class:

Public Class Book

    ''' <summary>
    ''' Gets or sets the book's ID. This must correspond to a key in the GlobalMembers.Books dictionary!
    ''' </summary>
    ''' <remarks></remarks>
    Public Property ID As String

    ''' <summary>
    ''' Gets or sets the name of the book.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Name As String

    ''' <summary>
    ''' Gets the display name of the book.
    ''' </summary>
    ''' <remarks></remarks>
    Public ReadOnly Property DisplayName As String
        Get
            'The text to display in for example a ListBox.
            Return Me.Name & " --- " & Me.ID
        End Get
    End Property

    ''' <summary>
    ''' Initializes a new instance of the Book class.
    ''' </summary>
    ''' <param name="Name">The name of the book.</param>
    ''' <param name="ID">The book's ID. This must correspond to a key in the GlobalMembers.Books dictionary!</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Name As String, ByVal ID As String)
        Me.Name = Name
        Me.ID = ID
    End Sub
End Class

Media class:

Public Class Media

    ''' <summary>
    ''' Gets or sets the media's ID. This must correspond to a key in the GlobalMembers.NonBookMedia dictionary!
    ''' </summary>
    ''' <remarks></remarks>
    Public Property ID As String

    ''' <summary>
    ''' Gets or sets the name of the media.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Name As String

    ''' <summary>
    ''' Gets or sets the media type.
    ''' </summary>
    ''' <remarks></remarks>
    Public Property Type As String

    ''' <summary>
    ''' Gets the display name of the media.
    ''' </summary>
    ''' <remarks></remarks>
    Public ReadOnly Property DisplayName As String
        Get
            'The text to display in for example a ListBox.
            Return Me.Type & " - " & Me.Name & " --- " & Me.ID
        End Get
    End Property

    ''' <summary>
    ''' Initializes a new instance of the Media class.
    ''' </summary>
    ''' <param name="Name">The name of the media.</param>
    ''' <param name="ID">The media's ID. This must correspond to a key in the GlobalMembers.NonBookMedia dictionary!</param>
    ''' <param name="Type">The media type (e.g. CD, DVD, etc.)</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal Name As String, ByVal ID As String, ByVal Type As String)
        Me.Name = Name
        Me.ID = ID
        Me.Type = Type
    End Sub
End Class

For a better overview, here's a diagram over the classes that we've just designed:

Class Diagram


4. Moving the global variables to the module

Now that we have all necessary classes - Library, Book and Media - we can go ahead and move the global dictionaries to the module we created earlier. We're also going to change them a bit... Instead of each dictionary holding the Code/ID and Name of each item, they're going to hold the Code/ID and the actual item (be it a library, a book or some kind of media).

This helps us more easily reference the actual item we're trying to get, which (thanks to our classes) already contains all the information we may need about it.

The declarations now look like the following:

Friend Module GlobalMembers

    ''' <summary>
    ''' A lookup table of all existing libraries. The Key of each entry must be the same as Library.Code.
    ''' </summary>
    ''' <remarks></remarks>
    Public Libraries As New Dictionary(Of String, Library)

    ''' <summary>
    ''' A lookup table of all existing books. The Key of each entry must be the same as Book.ID.
    ''' </summary>
    ''' <remarks></remarks>
    Public Books As New Dictionary(Of String, Book)

    ''' <summary>
    ''' A lookup table of all existing non-book media. The Key of each entry must be the same as Media.ID.
    ''' </summary>
    ''' <remarks></remarks>
    Public NonBookMedia As New Dictionary(Of String, Media)

End Module


5. Setting up the ListBoxes

Now that we've got everything set up back-end it's time to configure our ListBoxes to work with the new structure, because instead of simply storing text in each box we're now going to store each and every object. This helps us out a lot as we can then directly reference the selected object without having to look it up in one of our dictionaries first.

In each form's Load event we're going to set the DisplayMember property of the ListBoxes, which tells them which property of each item they should use to determine what text to should display (this will be the DisplayName property).

NOTE:
We won't be setting the ValueMember property like I suggested in my previous answer, as it turns out for that to work the DataSource property has to be set as well. Sorry about that.

frmManager:

Private Sub frmManager_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    'Libraries.
    lstLibraries.DisplayMember = "DisplayName"

    'Books.
    lstBooks.DisplayMember = "DisplayName"

    'Non-book media.
    lstMedia.DisplayMember = "DisplayName"

    'The rest of your code...
End Sub

frmAssociationScreen:

Private Sub frmAssociationScreen_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    'Libraries.
    lstLibraries.DisplayMember = "DisplayName"

    'Books.
    lstAllBooks.DisplayMember = "DisplayName"
    lstBooksCurrLib.DisplayMember = "DisplayName"

    'Media.
    lstAllMedia.DisplayMember = "DisplayName"
    lstMediaCurrLib.DisplayMember = "DisplayName"


    'The rest of your code...
End Sub


6. Manipulating your lists

We've now built the entire base of our program. Finally onto the functionality.

Adding data to our dictionaries

Since our dictionaries now expects our custom classes, we have to initialize instances of them before we add them. Notice how a library's code and a book/media's ID is specified in two places.

Libraries.Add("SVSU", New Library("Zahnow Library", "SVSU"))
Libraries.Add("BR", New Library("Fleschner Memorial Library", "BR"))
Libraries.Add("SDJ", New Library("Scott D. James Technical Repository", "SDJ"))

Books.Add("104", New Book("Data Structures for Fun and Profit", "104"))
Books.Add("103", New Book("Doing More With Less - Naval Lint Art", "103"))
Books.Add("102", New Book("Interpretive Klingon Poetry", "102"))
Books.Add("105", New Book("Programming with the Bidgoli", "105"))
Books.Add("101", New Book("Zen and the Art of Appliance Wiring", "101"))

NonBookMedia.Add("201", New Media("IEEE Computer: the Hits", "201", "CD"))
NonBookMedia.Add("203", New Media("Databases and You: the Video Experience", "203", "DVD"))
NonBookMedia.Add("202", New Media("The Pirates of Silicon Valley", "202", "DVD"))

Refreshing the ListBoxes

Sub populatelstLibrary()
    lstLibraries.Items.Clear()

    For Each library In Libraries
        lstLibraries.Items.Add(library.Value) 'Add the entire Library object directly. The ListBox manages display for us.
    Next
End Sub

Sub populatelstBooks()
    lstBooks.Items.Clear()

    For Each book In Books
        lstBooks.Items.Add(book.Value) 'Same goes for books...
    Next
End Sub

Sub populatelstBookMedia()
    lstMedia.Items.Clear()

    For Each bookMedia In nonBookMedia
        lstMedia.Items.Add(bookMedia.Value) '...and non-book media.
    Next
End Sub

Removing items (frmManager):

Below is how you remove the selected library from frmManager. Using this new structure, we first have to get the selected library object from lstLibraries, then remove it from the dictionary using its Code.

The same procedure is done for books and non-book media.

Private Sub btnDeleteLibrary_Click(sender As System.Object, e As System.EventArgs) Handles btnDeleteLibrary.Click
    'Try casting the selected item as a Library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If an item is selected and casting succeeded the variable should not be null.
    If selectedLibrary IsNot Nothing Then

        'Remove from dictionary.
        Libraries.Remove(selectedLibrary.Code)

        'Refresh ListBox.
        populatelstLibrary()

    End If
End Sub

Refreshing the ListBoxes in frmAssociationScreen:

Since we are now aware of which library object we have selected and what it contains, we can filter the items in the lstAll... boxes and thus not show the ones that we've already added in our library.

Sub populatelstLibrary()
    lstLibraries.Items.Clear()

    For Each library In Libraries
        lstLibraries.Items.Add(library.Value)
    Next
End Sub

Sub populatelstBooks()
    lstAllBooks.Items.Clear()

    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    For Each book In Books

        'Add all books that are NOT already in the library.
        'Check the book's dictionary key against the values in Library.Books.
        If Not selectedLibrary.Books.Contains(book.Key) Then
            lstAllBooks.Items.Add(book.Value)
        End If

    Next
End Sub

Sub populatelstBookMedia()
    lstAllMedia.Items.Clear()

    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    For Each bookMedia In NonBookMedia

        'Add all media that is NOT already in the library.
        'Check the media's dictionary key against the values in Library.NonBookMedia.
        If Not selectedLibrary.NonBookMedia.Contains(bookMedia.Key) Then
            lstAllMedia.Items.Add(bookMedia.Value)
        End If

    Next
End Sub

Refreshing the ListBoxes of books/media already in the current library:

Sub populatelstBooksCurrLib()
    lstBooksCurrLib.Items.Clear()

    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Iterate all book IDs in the library.
    For Each ID In selectedLibrary.Books

        'Get the respective book from our dictionary (if the book doesn't exist it will be ignored).
        Dim book As Book = Nothing
        If Books.TryGetValue(ID, book) Then

            'Add the book to our ListBox.
            lstBooksCurrLib.Items.Add(book)

        End If

    Next
End Sub

Sub populatelstMediaCurrLib()
    lstMediaCurrLib.Items.Clear()

    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Iterate all media IDs in the library.
    For Each ID In selectedLibrary.NonBookMedia

        'Get the respective media from our dictionary (if the media doesn't exist it will be ignored).
        Dim media As Media = Nothing
        If NonBookMedia.TryGetValue(ID, Media) Then

            'Add the media to our ListBox.
            lstMediaCurrLib.Items.Add(media)

        End If

    Next
End Sub

Adding items from another list in frmAssociationScreen:

Now when we want to add a book or a non-book media from our lists, all we have to do is to add the selected item's ID to Library.Books or Library.NonBookMedia and refresh our lists!

Private Sub btnAddBook_Click(sender As System.Object, e As System.EventArgs) Handles btnAddBook.Click
    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Get the selected book.
    Dim selectedBook As Book = TryCast(lstAllBooks.SelectedItem, Book)

    'If no book is selected, do not continue.
    If selectedBook Is Nothing Then Return

    'Add the selected book to the library.
    'If we for some reason add a duplicate, HashSet.Add() will return False and no exception will be thrown, so we're good to go!
    selectedLibrary.Books.Add(selectedBook.ID)

    'Update lists.
    populatelstBooks()
    populatelstBooksCurrLib()
End Sub



Private Sub btnAddMedia_Click(sender As System.Object, e As System.EventArgs) Handles btnAddMedia.Click
    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Get the selected non-book media.
    Dim selectedMedia As Media = TryCast(lstAllMedia.SelectedItem, Media)

    'If no media is selected, do not continue.
    If selectedMedia Is Nothing Then Return

    'Add the selected media to the library.
    'If we for some reason add a duplicate, HashSet.Add() will return False and no exception will be thrown, so we're good to go!
    selectedLibrary.NonBookMedia.Add(selectedMedia.ID)

    'Update lists.
    populatelstBookMedia()
    populatelstMediaCurrLib()
End Sub

Removing items from a list in frmAssociationScreen:

Pretty much the same procedure as above is done when removing.

Private Sub btnRemoveBook_Click(sender As System.Object, e As System.EventArgs) Handles btnRemoveBook.Click
    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Get the selected book.
    Dim selectedBook As Book = TryCast(lstBooksCurrLib.SelectedItem, Book)

    'If no book is selected, do not continue.
    If selectedBook Is Nothing Then Return

    'Remove the selected book from the library.
    selectedLibrary.Books.Remove(selectedBook.ID)

    'Update lists.
    populatelstBooks()
    populatelstBooksCurrLib()
End Sub



Private Sub btnRemoveMedia_Click(sender As System.Object, e As System.EventArgs) Handles btnRemoveMedia.Click
    'Get the selected library.
    Dim selectedLibrary As Library = TryCast(lstLibraries.SelectedItem, Library)

    'If no library is selected, do not continue.
    If selectedLibrary Is Nothing Then Return

    'Get the selected non-book media.
    Dim selectedMedia As Media = TryCast(lstMediaCurrLib.SelectedItem, Media)

    'If no media is selected, do not continue.
    If selectedMedia Is Nothing Then Return

    'Remove the selected media from the library.
    selectedLibrary.NonBookMedia.Remove(selectedMedia.ID)

    'Update lists.
    populatelstBookMedia()
    populatelstMediaCurrLib()
End Sub


Final words

A lot to go through and quite a lot to refactor. But as you see with the little extra work put into the classes and some refactoring we were now able to shorten a lot of the main code and make it easier to read, understand and manipulate in the future.

Hope this helps!

Full project download link:
https://www.mydoomsite.com/sourcecodes/StackOverflow%20LibraryManagement.zip

Upvotes: 3

Related Questions