Linked Lists Sample Application - Altair Realtors
Linked Lists Sample Application - Altair Realtors
Introduction
A linked list is a collection where, if the list contains more than one item, every item holds a reference to the item previous or next to it. Serialization is the ability to send the values of an application to a medium. In this application, we will apply our knowldge of linked lists to create records for a fictional real estate company. The records of the application will be saved using JSON serialization.
Practical Learning: Introducing the Application
A Class for a Real Estate Property
In real estate, a property is primaily a place where people live, such as a house (a real estate property can be more than that but we are keeping our definition simple). Such a property is the basis of our project. To support it, we will create a simple class.
Practical Learning: Creating a Starting Class
namespace AltairRealtors { public class Property { public string PropertyNumber { get; set; } public string PropertyType { get; set; } public string Address { get; set; } public string City { get; set; } public string State { get; set; } public string ZIPCode { get; set; } public short Stories { get; set; } public short Bedrooms { get; set; } public float Bathrooms { get; set; } public int YearBuilt { get; set; } public string Condition { get; set; } public double MarketValue { get; set; } public string SaleStatus { get; set; } public string PictureFile { get; set; } // To determine that two properties are the same, // we will test only the property number. // We assume that if two properties have the same number, // then it is the same property public override bool Equals(object obj) { Property rep = (Property)obj; if (rep.PropertyNumber == PropertyNumber) return true; else return false; } // To avoid a compiler warning public override int GetHashCode() { return base.GetHashCode(); } } }
A Form to Create a Real Estate Property
We will need a form that can allow a user to create a real estate property. The form will essentially have the controls represented in the class that was just created.
Practical Learning: Creating a Starting Class
Control | (Name) | Text | Other Properties | |
Label | Property #: | |||
TextBox | txtPropertyNumber | |||
Label | Property Type: | |||
ComboBox | cbxPropertiesTypes | DropDownStyle: DropDownList Items: Unknown Townhouse Single Family Condominium |
||
Button | btnSelectPicture | Select Property Picture... | ||
Label | lblPictureFile | . | ||
Label | Address: | |||
TextBox | txtAddress | |||
PictureBox | pbxProperty | BorderStyle: Fixed3D SizeMode: AutoSize |
||
Label | City: | |||
TextBox | txtCity | |||
Label | State: | |||
TextBox | txtState | |||
Label | ZIP Code: | |||
TextBox | txtZIPCode | |||
Label | Stories: | |||
TextBox | txtStories | |||
Label | Bedrooms: | |||
TextBox | txtBedrooms | |||
Label | Bathrooms: | |||
TextBox | txtBathrooms | |||
Label | Year Built: | |||
TextBox | txtYearBuilt | |||
Label | Condition: | |||
ComboBox | cbxConditions | DropDownStyle: DropDownList Items: Unknown Excellent Good Shape Needs Remodeling Under Construction |
||
Label | Market Value: | |||
TextBox | txtMarketValue | |||
Label | Sale Status: | |||
ComboBox | cbxSaleStatus | DropDownStyle: DropDownList Items: Sold Available Unspecified |
||
Label | ___________________________________ | |||
Button | btnSaveProperty | Save Property Information | ||
Button | btnClose | Close |
using System.Text.Json; namespace AltairRealtors { public partial class PropertyNew : Form { public PropertyNew() { InitializeComponent(); } /* This method is used to reset the form. * It can be called when necessary. */ private void InitializeProperty() { txtPropertyNumber.Text = string.Empty; txtAddress.Text = string.Empty; txtCity.Text = string.Empty; txtState.Text = string.Empty; txtZIPCode.Text = string.Empty; txtStories.Text = string.Empty; txtYearBuilt.Text = string.Empty; txtBedrooms.Text = string.Empty; txtBathrooms.Text = string.Empty; txtMarketValue.Text = string.Empty; // We have a default property image lblPictureFile.Text = "C:\\Altair Realtors\\Generic1.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic1.png"); /* Whenever the picture of a property displays, * we will resize the form to show the whole picture. */ Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void PropertyNew_Load(object sender, EventArgs e) { InitializeProperty(); } private void btnSelectPicture_Click(object sender, EventArgs e) { // Display the Open File Dialog box to allow the user to select a picture if(ofdPropertyImage.ShowDialog() == DialogResult.OK) { // If the user successfully selects a picture, display it in the picture box pbxProperty.Image = Image.FromFile(ofdPropertyImage.FileName); lblPictureFile.Text = ofdPropertyImage.FileName; Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } private void btnSaveProperty_Click(object sender, EventArgs e) { // This variable will hold the whole list of properties string strProperties = string.Empty; // This variable is the list of properties. It is used as a linked list LinkedList<Property> properties = new LinkedList<Property>(); /* Normally, we will provide a property number for each property. * So the following two lines are practically useless. */ Random rndNumber = new Random(DateTime.Now.Millisecond); txtPropertyNumber.Text = rndNumber.Next(100000, 999999).ToString(); // Get a reference to the file that holds the list of real estate properties string strFileName = "C:\\Altair Realtors\\Properties.json"; // If a file that contains a list of properties was already created... if (File.Exists(strFileName) == true) { /* ... open it. Read the text of all the properties. * Put that list is the variable we had declared for it. */ strProperties = File.ReadAllText(strFileName); /* JSON deserialize the list to convert the document into a JSON format. * Store the list in a linked list variable we had declared. */ properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; } /* Create a new real estate property based on the values * the user should have provided in the Windows controls of the form. */ Property residence = new Property(); residence.PropertyNumber = txtPropertyNumber.Text; residence.PropertyType = cbxPropertiesTypes.Text; residence.Address = txtAddress.Text; residence.City = txtCity.Text; residence.State = txtState.Text; residence.ZIPCode = txtZIPCode.Text; residence.Stories = short.Parse(txtStories.Text); residence.YearBuilt = int.Parse(txtYearBuilt.Text); residence.Bedrooms = short.Parse(txtBedrooms.Text); residence.Bathrooms = float.Parse(txtBathrooms.Text); residence.Condition = cbxConditions.Text; residence.SaleStatus = cbxSaleStatus.Text; residence.MarketValue = double.Parse(txtMarketValue.Text); residence.PictureFile = lblPictureFile.Text; // Add the real estate property record in the linked list properties.AddFirst(residence); /* To prepare to serialize the list, make sure * the values follow the indentation of a JSON-based document. */ JsonSerializerOptions options = new JsonSerializerOptions(); options.WriteIndented = true; // JSON serialize the list string jsProperties = JsonSerializer.Serialize(properties, typeof(LinkedList<Property>), options); File.WriteAllText(strFileName, jsProperties); // After creating the record, reset the form in case the user wants to create another record. InitializeProperty(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Inserting a Record
One of the interesting operations of a collection class is when it has built-in functionality to insert a new record between two existing record or at the begining of the list. A linked list goes one step further. It allows you to insert an item before or after an existing one. We will allow the user to do this.
Practical Learning: Inserting a Record
Control | (Name) | Text | |
Label | Existing Property #: | ||
TextBox | txtExistingPropertyNumber | ||
Label | New Property #: | ||
TextBox | txtNewPropertyNumber | ||
TextBox | txtPropertyType | ||
Button | btnInsertProperty | Insert Property |
namespace AltairRealtors { public partial class PropertyInsert : Form { public PropertyInsert() { InitializeComponent(); } private void PropertyInsert_Load(object sender, EventArgs e) { lblPictureFile.Text = "C:\\Altair Realtors\\Generic1.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic1.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void btnSelectPicture_Click(object sender, EventArgs e) { if (ofdPropertyImage.ShowDialog() == DialogResult.OK) { pbxProperty.Image = Image.FromFile(ofdPropertyImage.FileName); lblPictureFile.Text = ofdPropertyImage.FileName; Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } } }
Updating a Record
One of the necessary operations of a database is the ability to update records. We will provide this functionality trough a form.
Practical Learning: Updating a Record
Control | (Name) | Text | Other Properties | |
Button | btnFind | Find | ||
Button | btnUpdateProperty | Update Property Information |
using System.Text.Json; namespace AltairRealtors { public partial class PropertyEditor : Form { public PropertyEditor() { InitializeComponent(); } private void ResetProperty() { txtPropertyNumber.Text = string.Empty; txtAddress.Text = string.Empty; txtCity.Text = string.Empty; txtState.Text = string.Empty; txtZIPCode.Text = string.Empty; txtStories.Text = string.Empty; txtYearBuilt.Text = string.Empty; txtBedrooms.Text = string.Empty; txtBathrooms.Text = string.Empty; txtMarketValue.Text = string.Empty; lblPictureFile.Text = "C:\\Altair Realtors\\Generic2.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic2.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } public void ShowProperty(string propNbr) { /* As you will find out later, the argument is provided by * the Properties Listing form. * Normally, that argument should always be provided. * Just in case it is not, don't do nothing. */ if (propNbr is null) return; /* Create a real estate property using * the property number that is passed to this function. */ Property residence = new(); residence.PropertyNumber = propNbr; // Prepare to get a list of real estate properties LinkedList<Property> properties; // This is the file that holds the list of real estate properties string strFileName = "C:\\Altair Realtors\\Properties.json"; // Find out whether a file for real estate properties was already created. if (File.Exists(strFileName) == true) { // If the file of real estate properties was already created, open it string strProperties = strProperties = File.ReadAllText(strFileName); /* Deserialize the file and store the list of real estate properties * in the linked list variable that had already been declared. */ properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; // Find the property in the list LinkedListNode<Property> property = properties.Find(residence)!; /* If the real estate property was found in the file, * update its record with the values the user provided in the form. */ if (residence is not null) { txtPropertyNumber.Text = propNbr; cbxPropertiesTypes.Text = property.Value.PropertyType; txtAddress.Text = property.Value.Address; txtCity.Text = property.Value.City; txtState.Text = property.Value.State; txtZIPCode.Text = property.Value.ZIPCode; txtStories.Text = property.Value.Stories.ToString(); txtYearBuilt.Text = property.Value.YearBuilt.ToString(); txtBedrooms.Text = property.Value.Bedrooms.ToString(); txtBathrooms.Text = property.Value.Bathrooms.ToString("f"); cbxConditions.Text = property.Value.Condition; cbxSaleStatus.Text = property.Value.SaleStatus; txtMarketValue.Text = property.Value.MarketValue.ToString("f"); lblPictureFile.Text = property.Value.PictureFile; pbxProperty.Image = Image.FromFile(property.Value.PictureFile!); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } } private void PropertyEditor_Load(object sender, EventArgs e) { lblPictureFile.Text = "E:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("E:\\Altair Realtors\\Generic3.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void btnFind_Click(object sender, EventArgs e) { if( string.IsNullOrEmpty(txtPropertyNumber.Text)) { MessageBox.Show("You must enter a property number.", "Altair Realtors", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } ShowProperty(txtPropertyNumber.Text); } private void btnSelectPicture_Click(object sender, EventArgs e) { if (ofdPropertyImage.ShowDialog() == DialogResult.OK) { pbxProperty.Image = Image.FromFile(ofdPropertyImage.FileName); lblPictureFile.Text = ofdPropertyImage.FileName; Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } private void btnUpdateProperty_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtPropertyNumber.Text)) { MessageBox.Show("You must enter a property number.", "Altair Realtors", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } LinkedList<Property> properties; string strFileName = "C:\\Altair Realtors\\Properties.json"; Property residence = new(); residence.PropertyNumber = txtPropertyNumber.Text; if (File.Exists(strFileName) == true) { string strProperties = strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; LinkedListNode<Property> property = properties.Find(residence)!; if (residence is not null) { property.Value.PropertyType = cbxPropertiesTypes.Text; property.Value.Address = txtAddress.Text; property.Value.City = txtCity.Text; property.Value.State = txtState.Text; property.Value.ZIPCode = txtZIPCode.Text; property.Value.Stories = short.Parse(txtStories.Text); property.Value.YearBuilt = int.Parse(txtYearBuilt.Text); property.Value.Bedrooms = short.Parse(txtBedrooms.Text); property.Value.Bathrooms = float.Parse(txtBathrooms.Text); property.Value.Condition = cbxConditions.Text; property.Value.SaleStatus = cbxSaleStatus.Text; property.Value.MarketValue = double.Parse(txtMarketValue.Text); property.Value.PictureFile = lblPictureFile.Text; JsonSerializerOptions options = new JsonSerializerOptions(); options.WriteIndented = true; string jsProperties = JsonSerializer.Serialize(properties, typeof(LinkedList<Property>), options); File.WriteAllText(strFileName, jsProperties); } ResetProperty(); } } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Deleting a Real Estate Property
If you have a record you don't need in your application, you can remove it. We will use a form to assist the user to do that.
Practical Learning: Introducing Linked Lists
Control | (Name) | Text | |
TextBox | txtPropertyType | ||
TextBox | txtCondition | ||
TextBox | txtSaleStatus | ||
Button | btnDeleteProperty | Delete Property Record |
using System.Text.Json; namespace AltairRealtors { public partial class PropertyDelete : Form { public PropertyDelete() { InitializeComponent(); } private void ResetProperty() { txtPropertyNumber.Text = string.Empty; txtAddress.Text = string.Empty; txtCity.Text = string.Empty; txtState.Text = string.Empty; txtZIPCode.Text = string.Empty; txtStories.Text = string.Empty; txtYearBuilt.Text = string.Empty; txtBedrooms.Text = string.Empty; txtBathrooms.Text = string.Empty; txtMarketValue.Text = string.Empty; lblPictureFile.Text = "C:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic3.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } public void ShowProperty(string propNbr) { if (propNbr is null) return; Property residence = new(); residence.PropertyNumber = propNbr; LinkedList<Property> properties; string strFileName = "C:\\Altair Realtors\\Properties.json"; if (File.Exists(strFileName) == true) { string strProperties = strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; LinkedListNode<Property> property = properties.Find(residence)!; if (residence is not null) { txtPropertyNumber.Text = propNbr; txtPropertyType.Text = property.Value.PropertyType; txtAddress.Text = property.Value.Address; txtCity.Text = property.Value.City; txtState.Text = property.Value.State; txtZIPCode.Text = property.Value.ZIPCode; txtStories.Text = property.Value.Stories.ToString(); txtYearBuilt.Text = property.Value.YearBuilt.ToString(); txtBedrooms.Text = property.Value.Bedrooms.ToString(); txtBathrooms.Text = property.Value.Bathrooms.ToString("f"); txtCondition.Text = property.Value.Condition; txtSaleStatus.Text = property.Value.SaleStatus; txtMarketValue.Text = property.Value.MarketValue.ToString("f"); lblPictureFile.Text = property.Value.PictureFile; pbxProperty.Image = Image.FromFile(property.Value.PictureFile!); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } } private void PropertyDelete_Load(object sender, EventArgs e) { lblPictureFile.Text = "E:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("E:\\Altair Realtors\\Generic3.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void btnFind_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtPropertyNumber.Text)) { MessageBox.Show("You must enter a property number.", "Altair Realtors", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } ShowProperty(txtPropertyNumber.Text); } private void btnDeleteProperty_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(txtPropertyNumber.Text)) { MessageBox.Show("You must enter a property number.", "Altair Realtors", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } LinkedList<Property> properties; string strFileName = "C:\\Altair Realtors\\Properties.json"; Property residence = new() { PropertyNumber = txtPropertyNumber.Text }; if (File.Exists(strFileName) == true) { string strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; LinkedListNode<Property> property = properties.Find(residence)!; if (residence is not null) { properties.Remove(property); JsonSerializerOptions options = new JsonSerializerOptions(); options.WriteIndented = true; string jsProperties = JsonSerializer.Serialize(properties, typeof(LinkedList<Property>), options); File.WriteAllText(strFileName, jsProperties); } ResetProperty(); } } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Reviewing the Real Estate Properties
One of the most valuable functionalities of a linked list is that items of the list are linked. This allows you to navigate easily from one record to another. We will provided this functionality in our application.
Practical Learning: Introducing Linked Lists
Control | (Name) | Text | |
TextBox | txtPropertyType | ||
TextBox | txtCondition | ||
TextBox | txtSaleStatus | ||
Button | btnFirst | First | |
Button | btnPrevious | Previous | |
Label | lblRecordNumber | 000 of 000 | |
Button | btnNext | Next | |
Button | btnLast | Last | |
Button | btnClose | Close |
using System.Text.Json; namespace AltairRealtors { public partial class PropertiesReview : Form { int index; LinkedList<Property> Properties { get; set; } = new LinkedList<Property>(); LinkedListNode<Property>? Current; public PropertiesReview() { InitializeComponent(); } private void PropertiesReview_Load(object sender, EventArgs e) { string strFileName = "C:\\Altair Realtors\\Properties.json"; if (File.Exists(strFileName) == true) { string strProperties = File.ReadAllText(strFileName); Properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; btnFirst_Click(sender, e); } } private void btnFirst_Click(object sender, EventArgs e) { index = 1; Current = Properties.First!; txtPropertyNumber.Text = Current.Value.PropertyNumber; txtPropertyType.Text = Current.Value.PropertyType; txtAddress.Text = Current.Value.Address; txtCity.Text = Current.Value.City; txtState.Text = Current.Value.State; txtZIPCode.Text = Current.Value.ZIPCode; txtStories.Text = Current.Value.Stories.ToString(); txtYearBuilt.Text = Current.Value.YearBuilt.ToString(); txtBedrooms.Text = Current.Value.Bedrooms.ToString(); txtBathrooms.Text = Current.Value.Bathrooms.ToString("F"); txtCondition.Text = Current.Value.Condition; txtSaleStatus.Text = Current.Value.SaleStatus; txtMarketValue.Text = Current.Value.MarketValue.ToString("F"); if (Current.Value.PictureFile is null) { lblPictureFile.Text = "C:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic3.png"); } else { lblPictureFile.Text = Current.Value.PictureFile; pbxProperty.Image = Image.FromFile(Current.Value.PictureFile); } Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void btnPrevious_Click(object sender, EventArgs e) { index--; if (index <= 1) btnFirst_Click(sender, e); else { Current = Current?.Previous!; txtPropertyNumber.Text = Current?.Value.PropertyNumber; txtPropertyType.Text = Current?.Value.PropertyType; txtAddress.Text = Current?.Value.Address; txtCity.Text = Current?.Value.City; txtState.Text = Current?.Value.State; txtZIPCode.Text = Current?.Value.ZIPCode; txtStories.Text = Current?.Value.Stories.ToString(); txtYearBuilt.Text = Current?.Value.YearBuilt.ToString(); txtBedrooms.Text = Current?.Value.Bedrooms.ToString(); txtBathrooms.Text = Current?.Value.Bathrooms.ToString("F"); txtCondition.Text = Current?.Value.Condition; txtSaleStatus.Text = Current?.Value.SaleStatus; txtMarketValue.Text = Current?.Value.MarketValue.ToString("F"); if (Current?.Value.PictureFile is null) { lblPictureFile.Text = "C:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic3.png"); } else { lblPictureFile.Text = Current.Value.PictureFile; pbxProperty.Image = Image.FromFile(Current.Value.PictureFile); } Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } private void btnNext_Click(object sender, EventArgs e) { index++; if (index >= Properties.Count) btnLast_Click(sender, e); else { Current = Current?.Next; txtPropertyNumber.Text = Current?.Value.PropertyNumber; txtPropertyType.Text = Current?.Value.PropertyType; txtAddress.Text = Current?.Value.Address; txtCity.Text = Current?.Value.City; txtState.Text = Current?.Value.State; txtZIPCode.Text = Current?.Value.ZIPCode; txtStories.Text = Current?.Value.Stories.ToString(); txtYearBuilt.Text = Current?.Value.YearBuilt.ToString(); txtBedrooms.Text = Current?.Value.Bedrooms.ToString(); txtBathrooms.Text = Current?.Value.Bathrooms.ToString("F"); txtCondition.Text = Current?.Value.Condition; txtSaleStatus.Text = Current?.Value.SaleStatus; txtMarketValue.Text = Current?.Value.MarketValue.ToString("F"); if (Current?.Value.PictureFile is null) { lblPictureFile.Text = "C:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic3.png"); } else { lblPictureFile.Text = Current.Value.PictureFile; pbxProperty.Image = Image.FromFile(Current.Value.PictureFile); } Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } } private void btnLast_Click(object sender, EventArgs e) { index = Properties.Count; Current = Properties.Last; txtPropertyNumber.Text = Current?.Value.PropertyNumber; txtPropertyType.Text = Current?.Value.PropertyType; txtAddress.Text = Current?.Value.Address; txtCity.Text = Current?.Value.City; txtState.Text = Current?.Value.State; txtZIPCode.Text = Current?.Value.ZIPCode; txtStories.Text = Current?.Value.Stories.ToString(); txtYearBuilt.Text = Current?.Value.YearBuilt.ToString(); txtBedrooms.Text = Current?.Value.Bedrooms.ToString(); txtBathrooms.Text = Current?.Value.Bathrooms.ToString("F"); txtCondition.Text = Current?.Value.Condition; txtSaleStatus.Text = Current?.Value.SaleStatus; txtMarketValue.Text = Current?.Value.MarketValue.ToString("F"); if (Current?.Value.PictureFile is null) { lblPictureFile.Text = "C:\\Altair Realtors\\Generic3.png"; pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic3.png"); } else { lblPictureFile.Text = Current.Value.PictureFile; pbxProperty.Image = Image.FromFile(Current.Value.PictureFile); } Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Presenting the Application
Of course the most fundamental aspect of an application is to be presented to the user. This is usually done from the main form. In the central form of our application, we will create various links that can lead the user to other forms of the application. The central form is alwo used to display the list of the real estate properties of our application
Practical Learning: Presenting the Application
(Name) | Enabled | Text |
mnuAddProperty | Add Real Estate Property... | |
- | ||
mnuInsertBefore | False | Insert New Property Before... |
mnuInsertAfter | False | Insert New Property After... |
- | ||
mnuEditProperty | False | Edit Real Estate Property... |
mnuDeleteProperty | False | Delete/Remove Property... |
(Name) | Text | TextAlign | Width |
colPropertyNumber | Property # | 100 | |
colCity | City | 125 | |
colStories | Stories | Right | 65 |
colBedrooms | Beds | Right | 50 |
colBathrooms | Baths | Right | 60 |
colYearBuilt | Year | Right | 60 |
colCondition | Condition | 125 | |
colMarketValue | Value | Right | 125 |
colSaleStatus | Status | 100 |
Header | Name |
Condominium | lvgCondominium |
Townhouse | lvgTownhouse |
Single Family | lvgSingleFamily |
Control | (Name) | Text | Other Properties | |
ListView | lvwProperties | ContextMenuStrip: cmsProperties | ||
PictureBox | pbxPicture | BorderStyle: Fixed3D SizeMode: AutoSize |
||
Button | btnNewProperty | New Real Estate Property... | ||
Button | btnUpdatePropertyDetails | Update Property Details... | ||
Button | btnDeleteOrRemoveProperty | Delete/Remove Property... | ||
Button | btnPropertiesReview | Properties Review... | ||
Button | btnClose | Close |
using System.Text.Json; namespace AltairRealtors { public enum Insertion { Before, After, Unknown } public partial class PropertiesListing : Form { public PropertiesListing() { InitializeComponent(); } private void InitializePropertiesListing() { string strFileName = "C:\\Altair Realtors\\Properties.json"; LinkedList<Property> properties; // Make sure the file exists if (File.Exists(strFileName) == true) { string strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; // First, empty the list view lvwProperties.Items.Clear(); ListViewItem lviProperty; // Visit each property in the collection and add it to the list view foreach (Property house in properties) { if (house!.PropertyType!.Equals("Condominium")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[0]); else if (house.PropertyType.Equals("Townhouse")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[1]); else // if (house.PropertyType.Equals("Single Family")) lviProperty = new ListViewItem(house.PropertyNumber, lvwProperties.Groups[2]); lviProperty.SubItems.Add(house.City); lviProperty.SubItems.Add(house.Stories.ToString()); lviProperty.SubItems.Add(house.Bedrooms.ToString()); lviProperty.SubItems.Add(house.Bathrooms.ToString("F")); lviProperty.SubItems.Add(house.YearBuilt.ToString()); lviProperty.SubItems.Add(house.Condition); lviProperty.SubItems.Add(house.SaleStatus); lviProperty.SubItems.Add(house.MarketValue.ToString()); lviProperty.SubItems.Add(house.PictureFile); lvwProperties.Items.Add(lviProperty); } } pbxProperty.Image = Image.FromFile("C:\\Altair Realtors\\Generic.png"); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; } private void PropertiesListing_Load(object sender, EventArgs e) { InitializePropertiesListing(); } private void lvwProperties_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e) { if(lvwProperties.SelectedItems.Count == 0) return; string strFileName = "C:\\Altair Realtors\\Properties.json"; LinkedList<Property> properties; if (File.Exists(strFileName) == true) { string strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; foreach (Property house in properties) { if (house.PropertyNumber!.Equals(lvwProperties.SelectedItems[0]!.Text)) { pbxProperty.Image = Image.FromFile(house.PictureFile!); Width = pbxProperty.Right + 40; Height = pbxProperty.Bottom + 75; break; } } } if (lvwProperties.SelectedItems.Count == 1) { mnuInsertBefore.Enabled = true; mnuEditProperty.Enabled = true; mnuInsertAfter.Enabled = true; mnuDeleteProperty.Enabled = true; } else { mnuInsertBefore.Enabled = false; mnuEditProperty.Enabled = false; mnuInsertAfter.Enabled = false; mnuDeleteProperty.Enabled = false; } } private void lvwProperties_DoubleClick(object sender, EventArgs e) { PropertyEditor pe = new(); pe.ShowProperty(lvwProperties.SelectedItems[0].Text); pe.ShowDialog(); InitializePropertiesListing(); } private void btnNewProperty_Click(object sender, EventArgs e) { PropertyNew pn = new PropertyNew(); pn.ShowDialog(); InitializePropertiesListing(); } private void btnUpdatePropertyDetails_Click(object sender, EventArgs e) { PropertyEditor pe = new PropertyEditor(); pe.ShowDialog(); InitializePropertiesListing(); } private void btnDeleteOrRemoveProperty_Click(object sender, EventArgs e) { PropertyDelete pd = new(); pd.ShowDialog(); InitializePropertiesListing(); } private void mnuAddProperty_Click(object sender, EventArgs e) { btnNewProperty_Click(sender, e); InitializePropertiesListing(); } private void InsertProperty(Insertion decision) { LinkedList<Property> properties = new(); LinkedListNode<Property>? existing = null; string strFileName = "C:\\Altair Realtors\\Properties.json"; Property selected = new(); selected.PropertyNumber = lvwProperties.SelectedItems[0].Text; if (File.Exists(strFileName) == true) { string strProperties = strProperties = File.ReadAllText(strFileName); properties = JsonSerializer.Deserialize<LinkedList<Property>>(strProperties)!; existing = properties.Find(selected)!; } PropertyInsert pi = new PropertyInsert(); Random rndNumber = new Random(DateTime.Now.Millisecond); pi.txtNewPropertyNumber.Text = rndNumber.Next(100000, 999999).ToString(); pi.txtExistingPropertyNumber.Text = lvwProperties.SelectedItems[0].Text; pi.txtPropertyType.Text = lvwProperties.SelectedItems[0].Group.ToString(); if (decision == Insertion.Before) { pi.Text = "Altair Realtors - Property Insertion - Before"; pi.btnInsertProperty.Text = "Insert Property Before [" + lvwProperties.SelectedItems[0].Text + "]"; } else { pi.Text = "Altair Realtors - Property Insertion - After"; pi.btnInsertProperty.Text = "Insert Property After [" + lvwProperties.SelectedItems[0].Text + "]"; } if (pi.ShowDialog() == DialogResult.OK) { Property residence = new(); residence.PropertyNumber = pi.txtNewPropertyNumber.Text; residence.PropertyType = pi.txtPropertyType.Text; residence.Address = pi.txtAddress.Text; residence.City = pi.txtCity.Text; residence.State = pi.txtState.Text; residence.ZIPCode = pi.txtZIPCode.Text; residence.Stories = short.Parse(pi.txtStories.Text); residence.YearBuilt = int.Parse(pi.txtYearBuilt.Text); residence.Bedrooms = short.Parse(pi.txtBedrooms.Text); residence.Bathrooms = float.Parse(pi.txtBathrooms.Text); residence.Condition = pi.cbxConditions.Text; residence.SaleStatus = pi.cbxSaleStatus.Text; residence.MarketValue = double.Parse(pi.txtMarketValue.Text); residence.PictureFile = pi.lblPictureFile.Text; if(decision == Insertion.Before) { properties.AddBefore(existing!, residence); } else { properties.AddAfter(existing!, residence); } JsonSerializerOptions options = new JsonSerializerOptions(); options.WriteIndented = true; string jsProperties = JsonSerializer.Serialize(properties, typeof(LinkedList<Property>), options); File.WriteAllText(strFileName, jsProperties); } InitializePropertiesListing(); } private void mnuInsertBefore_Click(object sender, EventArgs e) { InsertProperty(Insertion.Before); InitializePropertiesListing(); } private void mnuInsertAfter_Click(object sender, EventArgs e) { InsertProperty(Insertion.After); InitializePropertiesListing(); } private void mnuEditProperty_Click(object sender, EventArgs e) { lvwProperties_DoubleClick(sender, e); InitializePropertiesListing(); } private void mnuDeleteProperty_Click(object sender, EventArgs e) { PropertyDelete pd = new(); pd.ShowProperty(lvwProperties.SelectedItems[0].Text); pd.ShowDialog(); InitializePropertiesListing(); } private void btnPropertiesReview_Click(object sender, EventArgs e) { PropertiesReview pr = new PropertiesReview(); pr.ShowDialog(); } private void btnClose_Click(object sender, EventArgs e) { Close(); } } }
Executing and Testing the Application
After creating the project, you can test it with sample values and operations.
Practical Learning: Executing and Testing the Application
Property # | Property Type | Address | City | State | ZIP Code | Stories | Bedrooms | Bathrooms | Year Built | Condition | Market Value | Sale Status | Picture File |
770686 | Single Family | 4288 Lucow Drive | Rockville | Maryland | 20856 | 3 | 5 | 3.5 | 1988 | Excellent | 665580 | Available | Single-Family-5 |
250351 | Townhouse | 719 Beanson Road | Arlington | Virginia | 22201 | 4 | 4 | 3.5 | 1995 | Good Shape | 580795 | Sold | Townhouse-4 |
264649 | Condominium | 6662 16th Street NW | Washington | DC | 20012 | 2 | 1 | 1 | 1984 | Good Shape | 325775 | Available | Building-3 |
975700 | Single Family | 39 Anesta Court | Gettysburg | Pennsylvania | 17325 | 2 | 3 | 2.5 | 1988 | Excellent | 665580 | Available | Single-Family-4 |
575370 | Condominium | 10574 Spring Floor Road | Hinesville | Georgia | 31313 | 4 | 2 | 2 | 2014 | Good Shape | 235775 | Available | Building-2 |
747575 | Townhouse | 228 South Gather Street | Blanchard | Oklahoma | 73010 | 3 | 4 | 3.5 | 2020 | Excellent | 380795 | Sold | Townhouse-2 |
375705 | Single Family | 8604 Bridge Stone Avenue | Brecken Ridge | Colorado | 80824 | 3 | 3 | 4.5 | 2022 | Unknown | 655800 | Available | Single-Family-1 |
886868 | Condominium | 2644 Swanson Drive | Charleston | West Virginia | 25301 | 4 | 3 | 2 | 2004 | Good Shape | 225450 | Available | Building-4 |
694708 | Single Family | 508 North Harrison Street | Papillion | Nebraska | 68046 | 2 | 4 | 2.5 | 1986 | Unknown | 352500 | Sold | Single-Family-3 |
164086 | Townhouse | 4220 Melmann Drive | Baltimore | Maryland | 21206 | 3 | 3 | 2.5 | 1982 | Needs Remodeling | 325970 | Available | Townhouse-1 |
369359 | Single Family | 8905 Mandarin Road | McLean | Virginia | 22102 | 3 | 5 | 3.5 | 1992 | Unknown | 785680 | Available | Single-Family-6 |
864968 | Townhouse | 2428 Connecticut Avenue | Washington | DC | 20008 | 3 | 3 | 2.5 | 2015 | Needs Remodeling | 385600 | Sold | Townhouse-3 |
557357 | Single Family | 10202 Lockwood Ave | Sherman | Illinois | 62684 | 3 | 5 | 3.5 | 2022 | Under Construction | 675880 | Sold | Single-Family-2 |
288206 | Condominium | 808D Green Tree Road | Arbovale | West Virginia | 24915 | 3 | 1 | 1 | 2006 | Unknown | 216925 | Available | Building-1 |
Home | Copyright © 2014-2023, FunctionX | Friday 09 December 2022 | Home |