Practice Sorting Custom Classes in Visual Basic.NET

Lab Scenario

You are a developer for Northrup Realty, Inc., an organization that specializes in finding commercial and home real estate for buyers in different countries. Your task is to create classes that you and other developers can use to create a .NET Framework application that will allow potential buyers to browse real estate.

To achieve your goals, you will create a base class that represents any type of real estate. Then, you will create custom classes to represent commercial real estate, condominiums, and homes. Next, you will write code to allow a collection of lots to be sorted in different ways. Finally, you will create a user interface for the classes and leverage regular expressions to verify user input.

While the point of this exercise is for you to complete it yourself, you can download the completed solution here: Completed Real Estate Project in Visual Basic.

Exercise 1: Create Base Classes

Your manager has asked you to create an extensible, flexible class structure for different types of lots. Initially, you will create classes for commercial lots (that might be used by warehouses, retail stores, or other businesses), condominiums, and private residences. Your structure should be flexible enough to allow you to add other classes in the future, including multi-family homes, farms, and undeveloped land.

The main tasks for this exercise are as follows:

  1. Create a WPF Application in either Visual Basic.NET or C#.
  2. Create a base class call Lot.
  3. From the base Lot class, create a Commercial class.
  4. From the base Lot class, create a Home class.
  5. From the base Home class, create a Condo class.

Task 1: Create a WPF Application in either Visual Basic.NET or C#.

  1. Launch Visual Studio.
  2. Create a new WPF Application project in either Visual C# or Visual Basic. Name the application RealEstate.

Task 2: Create the base Lot class

  1. Add an abstract class to the project named Lot. In C#, use the abstract keyword. In Visual Basic, use the MustInherit keyword. You cannot create an instance of an abstract class. However, you can create classes that inherit from abstract classes. Because we are going to use Lot strictly as a base class, it is a perfect example of when to create an abstract class.
  2. Add the following private properties to the new class:
  • _price (of type Integer)
  • _squareFeet (of type Integer)
  • _acres (of type Double)
  • _streetAddress (of type String)
  • _city (of type String)
  • _state (of type String)
  • _zip (of type String)
  • _listingDate (of type DateTime)
  • _buildDate (of type DateTime)
  1. Add public properties for each of the private properties. In the Get function, return the value from the corresponding private property. In the Set function, write code to validate the value. Use regular expressions to validate the zip code—this will require you to add the System.Text.RegularExpressions namespace. Throw an ArgumentOutOfRangeException exception if the input is invalid.
  2. Override the default ToString method. When ToString is called, return the address and the price of the Lot. You can also return the acreage and square feet.
  3. The Visual Basic code should resemble the following:
Imports System.Text.RegularExpressions

Public MustInherit Class Lot
    Private _price As Integer
    Private _squareFeet As Integer
    Private _acres As Double
    Private _streetAddress As String
    Private _city As String
    Private _state As String
    Private _zip As String
    Private _listingDate As DateTime
    Private _buildDate As DateTime

    Public Property Price() As Integer
        Get
            Return _price
        End Get

        Set(ByVal value As Integer)
            If value > 0 Then
                _price = value
            Else
                Throw New ArgumentOutOfRangeException("Price must be a positive value")
            End If
        End Set
    End Property

    Public Property SquareFeet() As Integer
        Get
            Return _squareFeet
        End Get

        Set(ByVal value As Integer)
            If value > 0 Then
                _squareFeet = value
            Else
                Throw New ArgumentOutOfRangeException("SquareFeet must be a positive value")
            End If
        End Set
    End Property

    Public Property Acres() As Double
        Get
            Return _acres
        End Get

        Set(ByVal value As Double)
            If value > 0 Then
                _acres = value
            Else
                Throw New ArgumentOutOfRangeException("Acres must be a positive value")
            End If
        End Set
    End Property

    Public Property StreetAddress() As String
        Get
            Return _streetAddress
        End Get
        Set(ByVal value As String)
            If value.Length > 0 Then
                _streetAddress = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a value for StreetAddress")
            End If
        End Set
    End Property

    Public Property City() As String
        Get
            Return _city
        End Get
        Set(ByVal value As String)
            If value.Length > 0 Then
                _city = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a value for City")
            End If
        End Set
    End Property

    Public Property State() As String
        Get
            Return _state
        End Get
        Set(ByVal value As String)
            If value.Length = 2 Then
                _state = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a two-character value for State")
            End If
        End Set
    End Property

    Public Property Zip() As String
        Get
            Return _zip
        End Get
        Set(ByVal value As String)
            If Regex.IsMatch(value, "^\d{5}(\-\d{4})?$") Then
                _zip = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a valid zip code for Zip")
            End If
        End Set
    End Property

    Public Property ListingDate() As DateTime
        Get
            Return _listingDate
        End Get
        Set(ByVal value As DateTime)
            If value.Year > 1900 Then
                _listingDate = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a valid date, later than the year 1900, for the ListingDate")
            End If
        End Set
    End Property

    Public Property BuildDate() As DateTime
        Get
            Return _buildDate
        End Get
        Set(ByVal value As DateTime)
            If value.Year > 0 Then
                _buildDate = value
            Else
                Throw New ArgumentOutOfRangeException("You must provide a valid date, later than the year 0, for the BuildDate")
            End If
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return String.Format("{0}, {1}, {2}: ${3}", StreetAddress, City, State, Price)
    End Function

End Class

Task 3: Create the Commercial class

  1. Add a class to the project named Commercial.
  2. Derive the class from Lot.
  3. Create an Enumeration type named CommercialLotType, with options for ShoppingCenter, Restaurant, Office, Storage, and Parking.
  4. Add the following public lots to the new class:
  • SignVisible (of type Boolean)
  • Type (of type CommercialLotType)
  1. Create a constructor that accepts parameters for every Lot defined by both Commercial and the base Lot class.

The Visual Basic code should resemble the following:

Public Class Commercial
    Inherits Lot
    Public Enum CommercialLotType
        ShoppingCenter
        Restaurant
        Office
        Storage
        Parking
    End Enum

    Public SignVisible As Boolean
    Public Type As CommercialLotType

    Public Sub New(ByVal _price As Integer, ByVal _squareFeet As Integer, ByVal _acres As Double, ByVal _streetAddress As String, ByVal _city As String, ByVal _state As String, _
     ByVal _zip As String, ByVal _listingDate As DateTime, ByVal _buildDate As DateTime, ByVal _type As CommercialLotType, ByVal _signVisible As Boolean)
        Me.Price = _price
        Me.SquareFeet = _squareFeet
        Me.Acres = _acres
        Me.StreetAddress = _streetAddress
        Me.City = _city
        Me.State = _state
        Me.Zip = _zip
        Me.ListingDate = _listingDate
        Me.BuildDate = _buildDate
        Me.Type = _type
        Me.SignVisible = _signVisible
    End Sub
End Class

Task 4: Create the Home class

  1. Add a class to the project named Home.
  2. Derive the class from Lot.
  3. Create an Enumeration type named HomeLotType, with options for SingleFamily, MultiFamily, Mobile.
  4. Add the following public lots to the new class:
  • Bedrooms (of type Int)
  • Bathrooms (of type Int)
  • Type (of type HomeLotType)
  1. Create a constructor that accepts parameters for every property defined by both Home and the base Lot class.
  2. Create a constructor that accepts zero parameters. This will be required when you derive the Condo class from the Home class.

The VB code should resemble the following:

Class Home
    Inherits Lot
    Public Enum HomeLotType
        SingleFamily
        MultiFamily
        Mobile
    End Enum

    Public Bedrooms As Integer
    Public Bathrooms As Integer
    Public Type As HomeLotType

    Public Sub New(ByVal _price As Integer, ByVal _squareFeet As Integer, ByVal _acres As Double, ByVal _streetAddress As String, ByVal _city As String, ByVal _state As String, _
     ByVal _zip As String, ByVal _listingDate As DateTime, ByVal _buildDate As DateTime, ByVal _bedrooms As Integer, ByVal _bathrooms As Integer, ByVal _type As HomeLotType)
        Me.Price = _price
        Me.SquareFeet = _squareFeet
        Me.Acres = _acres
        Me.StreetAddress = _streetAddress
        Me.City = _city
        Me.State = _state
        Me.Zip = _zip
        Me.ListingDate = _listingDate
        Me.BuildDate = _buildDate
        Me.Type = _type
        Me.Bedrooms = _bedrooms
        Me.Bathrooms = _bathrooms
    End Sub

    Public Sub New()
    End Sub
End Class

Task 5: Create the Condo class

  1. Add a class to the project named Condo.
  2. Derive the class from Home.
  3. Add the following public lots to the new class:
  • Gym (of type Boolean)
  • Pool (of type Boolean)
  • MonthlyFees (of type Double)
  1. Create a constructor that accepts parameters for every property defined by Condo, the base Home class, and the base Lot class. Do not define the Home.Type class, however.

The VB code should resemble the following:

Class Condo
    Inherits Home
    Public Gym As Boolean
    Public Pool As Boolean
    Public MonthlyFees As Double

    Public Sub New(ByVal _price As Integer, ByVal _squareFeet As Integer, ByVal _acres As Double, ByVal _streetAddress As String, ByVal _city As String, ByVal _state As String, _
     ByVal _zip As String, ByVal _listingDate As DateTime, ByVal _buildDate As DateTime, ByVal _bedrooms As Integer, ByVal _bathrooms As Integer, ByVal _gym As Boolean, _
     ByVal _pool As Boolean, ByVal _monthlyFees As Double)
        Me.Price = _price
        Me.SquareFeet = _squareFeet
        Me.Acres = _acres
        Me.StreetAddress = _streetAddress
        Me.City = _city
        Me.State = _state
        Me.Zip = _zip
        Me.ListingDate = _listingDate
        Me.BuildDate = _buildDate
        Me.Bedrooms = _bedrooms
        Me.Bathrooms = _bathrooms

        Me.Gym = _gym
        Me.Pool = _pool
        Me.MonthlyFees = _monthlyFees
    End Sub
End Class

Exercise 2: Enable Sorting

Task 1: Implement a default sorter in Lot

  1. In the Lot class, implement the generic IComparable interface using the Lot type.
  2. Override the CompareTo method, and compare based on the Lot.Price property.
  3. The CompareTo method should resemble the following:
Public Function CompareTo(l1 As Lot) As Integer
	Return Me.Price.CompareTo(l1.Price)
End Function

Task 2: Create a class named LotComparer, based on IComparer, that can sort by Price, SquareFeet, Acres, or City.

  1. Create a new class named LotComparer.
  2. Implement the generic IComparer interface.
  3. Create an enumeration named ComparisonType with values for Price, SquareFeet, Acres, and City.
  4. Create an instance of ComparisonType named ComparisonMethod.
  5. Override the Compare method to call the proper underlying CompareTo method. For example, if ComparisonMethod is set to SquareFeet, you should call the SquareFeet.CompareTo method. A switch command works well for this.

The new class should resemble the following in Visual Basic:

Public Class LotComparer
    Implements IComparer(Of Lot)
    Public Enum ComparisonType
        Price
        SquareFeet
        Acres
        City
    End Enum

    Public ComparisonMethod As ComparisonType

    Public Function Compare(ByVal p1 As Lot, ByVal p2 As Lot) As Integer Implements System.Collections.Generic.IComparer(Of Lot).Compare
        Select Case ComparisonMethod
            Case LotComparer.ComparisonType.SquareFeet
                Return p1.SquareFeet.CompareTo(p2.SquareFeet)
            Case LotComparer.ComparisonType.Acres
                Return p1.Acres.CompareTo(p2.Acres)
            Case LotComparer.ComparisonType.City
                Return p1.City.CompareTo(p2.City)
            Case Else
                Return p1.Price.CompareTo(p2.Price)
        End Select
    End Function
End Class

Exercise 3: Create the User Interface

Task 1: Design the XAML user interface

  1. Add a ComboBox named SortComboBox. Optionally, add a label beside the ComboBox that reads Sort by:.
  2. Add a ListBox named LotListBox.

The user interface should resemble the following:

Task 2: Populate the LotListBox

  1. Create a Window.Loaded event handler. The XAML Window declaration should now resemble the following:
<Window x:Class="RealEstate.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Real Estate" Height="199" Width="312"
    Loaded="Window_Loaded">
</Window>
  1. Within the Window1 class, add a Lot array named lots. Create 5 elements for the array.
  2. In the Window.Loaded event handler, create five instances of Commercial, Home, and Condo, and add them to the lots array. This should resemble:
lots(0) = New Commercial(500000, 10000, 1.5, "100 Cardinal Rd", "Anytown", "MA", "01331", DateTime.Now, New DateTime(2009, 9, 1), Commercial.CommercialLotType.Office, True)
lots(1) = New Home(250000, 2500, 0.5, "12 Bluejay St", "Mytown", "CT", "02492", DateTime.Now, New DateTime(1955, 5, 1), 2, 1, Home.HomeLotType.SingleFamily)
lots(2) = New Condo(150000, 1000, 0.1, "10 Crow Ave", "Yourtown", "VT", "12020", DateTime.Now, New DateTime(1963, 8, 3), 1, 1, True, True, 200)
lots(3) = New Commercial(750000, 12000, 5, "77 Eagle Cir", "Histown", "NH", "02439", DateTime.Now, New DateTime(2004, 3, 15), Commercial.CommercialLotType.Restaurant, True)
lots(4) = New Home(450000, 4500, 5.5, "12 Heron Blvd", "Hertown", "NY", "02394", DateTime.Now, New DateTime(1988, 7, 1), 5, 3, Home.HomeLotType.SingleFamily)
  1. Set the LotListBox.ItemsSource value to the lots array. The Window1 class should now resemble the following in C#:
Class Window1
    Private lots As Lot() = New Lot(4) {}

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        lots(0) = New Commercial(500000, 10000, 1.5, "100 Cardinal Rd", "Anytown", "MA", "01331", DateTime.Now, New DateTime(2009, 9, 1), Commercial.CommercialLotType.Office, True)
        lots(1) = New Home(250000, 2500, 0.5, "12 Bluejay St", "Mytown", "CT", "02492", DateTime.Now, New DateTime(1955, 5, 1), 2, 1, Home.HomeLotType.SingleFamily)
        lots(2) = New Condo(150000, 1000, 0.1, "10 Crow Ave", "Yourtown", "VT", "12020", DateTime.Now, New DateTime(1963, 8, 3), 1, 1, True, True, 200)
        lots(3) = New Commercial(750000, 12000, 5, "77 Eagle Cir", "Histown", "NH", "02439", DateTime.Now, New DateTime(2004, 3, 15), Commercial.CommercialLotType.Restaurant, True)
        lots(4) = New Home(450000, 4500, 5.5, "12 Heron Blvd", "Hertown", "NY", "02394", DateTime.Now, New DateTime(1988, 7, 1), 5, 3, Home.HomeLotType.SingleFamily)

        LotListBox.ItemsSource = lots
    End Sub
End Class

Task 3: Populate the SortComboBox

  1. In the Window.Loaded event handler, set the SortComboBox.ItemsSource value to the LotComparer.ComparisonType enumeration. You can do that using the following code:
SortComboBox.ItemsSource = [Enum].GetValues(GetType(LotComparer.ComparisonType))
  1. After you populate the SortComboBox, select the first item by setting SortComboBox.SelectedIndex to 0.
  1. Add the SortComboBox.SelectionChanged event handler to the XAML. The XAML for the SortComboBox should resemble the following:
<ComboBox Height="23" Margin="104,8,8,0" Name="SortComboBox" VerticalAlignment="Top" SelectionChanged="SortComboBox_SelectionChanged" />
  1. Implement the SortComboBox.SelectionChanged event handler so that the lots array is re-sorted by the selected item, and the LotListBox is refreshed. You can do that with the following code:
Private Sub SortComboBox_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
    Dim pc As New LotComparer()
    pc.ComparisonMethod = DirectCast(SortComboBox.SelectedItem, LotComparer.ComparisonType)
    Array.Sort(Of Lot)(lots, pc)

    LotListBox.Items.Refresh()
End Sub

Task 4: Test the application

  1. Run the application. Select different items in the SortComboBox and notice that the lots are re-sorted. The Window1 class should now resemble the following in VB:
Class Window1
    Private lots As Lot() = New Lot(4) {}

    Private Sub Window_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        lots(0) = New Commercial(500000, 10000, 1.5, "100 Cardinal Rd", "Anytown", "MA", "01331", DateTime.Now, New DateTime(2009, 9, 1), Commercial.CommercialLotType.Office, True)
        lots(1) = New Home(250000, 2500, 0.5, "12 Bluejay St", "Mytown", "CT", "02492", DateTime.Now, New DateTime(1955, 5, 1), 2, 1, Home.HomeLotType.SingleFamily)
        lots(2) = New Condo(150000, 1000, 0.1, "10 Crow Ave", "Yourtown", "VT", "12020", DateTime.Now, New DateTime(1963, 8, 3), 1, 1, True, True, 200)
        lots(3) = New Commercial(750000, 12000, 5, "77 Eagle Cir", "Histown", "NH", "02439", DateTime.Now, New DateTime(2004, 3, 15), Commercial.CommercialLotType.Restaurant, True)
        lots(4) = New Home(450000, 4500, 5.5, "12 Heron Blvd", "Hertown", "NY", "02394", DateTime.Now, New DateTime(1988, 7, 1), 5, 3, Home.HomeLotType.SingleFamily)

        LotListBox.ItemsSource = lots

        SortComboBox.ItemsSource = [Enum].GetValues(GetType(LotComparer.ComparisonType))
        SortComboBox.SelectedIndex = 0
    End Sub

    Private Sub SortComboBox_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs)
        Dim pc As New LotComparer()
        pc.ComparisonMethod = DirectCast(SortComboBox.SelectedItem, LotComparer.ComparisonType)
        Array.Sort(Of Lot)(lots, pc)

        LotListBox.Items.Refresh()
    End Sub
End Class

Lab Resources

While the point of this exercise is for you to complete it yourself, you can download the completed solution here: Completed Real Estate Project in Visual Basic.

Return to the .NET Framework Fundamentals Tutorials Table of Contents.

public partial class Window1 : Window

{

Lot[] lots = new Lot[5];

public Window1()

{

InitializeComponent();

}

private void Window_Loaded(object sender, RoutedEventArgs e)

{

lots[0] = new Commercial(500000, 10000, 1.5, “100 Cardinal Rd”, “Anytown”, “MA”, “01331″, DateTime.Now, new DateTime(2009, 9, 1), Commercial.CommercialLotType.Office, true);

lots[1] = new Home(250000, 2500, .5, “12 Bluejay St”, “Mytown”, “CT”, “02492″, DateTime.Now, new DateTime(1955, 5, 1), 2, 1, Home.HomeLotType.SingleFamily);

lots[2] = new Condo(150000, 1000, .1, “10 Crow Ave”, “Yourtown”, “VT”, “12020″, DateTime.Now, new DateTime(1963, 8, 3), 1, 1, true, true, 200);

lots[3] = new Commercial(750000, 12000, 5, “77 Eagle Cir”, “Histown”, “NH”, “02439″, DateTime.Now, new DateTime(2004, 3, 15), Commercial.CommercialLotType.Restaurant, true);

lots[4] = new Home(450000, 4500, 5.5, “12 Heron Blvd”, “Hertown”, “NY”, “02394″, DateTime.Now, new DateTime(1988, 7, 1), 5, 3, Home.HomeLotType.SingleFamily);

LotListBox.ItemsSource = lots;

}

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>