Assignment 2: Practice Good Form

Thank goodness Assignment 1 is over, because we will never again write another Console application in this class. Instead, we're going to transition into building Forms -- Microsoft's term for Graphical User Interface (GUI) based applications. What Java would refer to as JFrames, and what other languages and frameworks no doubt have unique names for as well, because we all need to be different from each other. Like the special, unique snowflakes we are, all effectively doing the same thing as each other... But I digress.

Specifically, we're going to build "Windows Form Applications (.NET Framework)" as they will appear in the list of available types of Projects we can build. This will be our canvas upon which we will place text fields, buttons, drop down menus (called ComboBox for some asinine reason), and radio buttons. Controls I geniunely hope we're all abundantly familiar with, with as integrated technology has become into our everyday lives. These virtual panels are meant to convey the very same interface as physical ones, such as Control panels. Where you can broadly divide the interface into two categories: information feedback, and mechanisms of user input. I push a button or pull a lever, followed by some kind of feedback representing the result of this action. We're going to do the same in these projects, only we won't physically touch any of these mechanisms.

To ease our transition into designing Forms for what might be the first time you're doing as much, we're going to simply upgrade our Assignment 1 work. That is, we're going to build a GUI for the Real Estate Mgmt. application we visualized through a Console Application, allowing us to finally use the mouse to select Residents and Properties, and to have much of this information better organized for our digestion, and static for ease of use. We're only going to be adding a few new features this time around, although you might find it necessary to include additional tools in the background to facilitate existing or new features, or to achieve their functionality more efficiently. I personally made a good number of changes to the classes I built in Assignment 1, to improve usability now that — for example, all my output isn't being dumped into Console.WriteLine. I'm encouraging you to make changes as you feel is necessary to best suit your needs.

Our input files for the DeKalb Community ( [Houses], [Apartments], and [Persons] ) haven't been changed at all. Instead, we're adding a second set of input fileds, for the Sycamore Community. ( [Houses], [Apartments], and [Persons] ) I don't recommend changing the names of the files themselves but instead, creating two separate directories within your project that stores them. For convenience, if you name the directories after the Name attribute of the Community objects (hint hint) you create, you can easily populate both Communities using the same ReadFile methods you hopefully used the first time around.

Actually, I did change something fundamental about the Persons input files. They now allow for residents to be initially defined as residing at multiple residences from the very beginning. Which shouldn't be too hard to accommodate for.

Additionally, I've intentionally "poisoned" the Sycamore p.txt and r.txt files to include someone with an identical ID value as someone else previously defined in that file, and a House record with fewer tokens than is minimally necessary to create an object from that class. Both of these records must be read by your program and summarily dealt with, either with Exception usage or simple if-statement checks. If it's discovered that you simply deleted the two offending records, you'll lose 10 points for each deletion.

Let's take a look at what I've put together to represent this improved Real Estate Mgmt. interface.

The Main Menu

By no means are you expected to replicate this design, pound for pound. You can, if you'd like or if you'd rather not bother with re-inventing the wheel. After all, it has already been invented and comes in cheese form. You are only expected to replicate this functionality, as well as some of the formatting, which is detailed below. You may add functionality to this for bonus Cool Person Points (which you can redeem at your nearest Dude Bro Ranch location), but you have to achieve everything described below, at a minimum.

Let's now cover what that minimum functionality entails:

Assignment 1

We're going to include every bit of functionality from Assignment 1, albeit with some twists on some of their implementation, since we know have a GUI to utilize. To re-cap:

  1. Full property list — this will be achieved by populating the corresponding ListBox, immediately after a Community RadioButton has been picked. Note: This involve a very different set of output as compared to what we did in Assignment 1
  2. List addresses of either House or Apartment-type properties — this will be achieved by partitioning the properties list into Houses, followed by Apartments, as well as cosmetic labelling
  3. List addresses of all for-sale properties — this will be realized by annotations next to each property in the ListBox
  4. List all residents of a community — similar to Full Property List
  5. List all residents of a property, by street address — this is achieved when the user selects a property from the ListBox
  6. Toggle a property, by street address, as being for-sale or not. — we'll include a Button for this
  7. Buy a for-sale property, by street address — Button for this, too
  8. Add yourself as an occupant to a property. — It's Button-o clock
  9. Remove yourself as an occupant from a property — rather than take your rear off, you're going to put your ButtOn
  10. Quit — we get this one for free, with Forms including that red X button in the top-right corner

Formatting

As you can see from the sample output screenshots provided at the end of this page, there are some requirements I would like to impose for some of these containers, if only to make utilizing them in this project interesting. The Residents ListBox will include only the person's first name, age, and occupation. But rather than making the ListBox wide enough to present every resident, we're going to impose a character limit on how much of their occupation will be displayed. Longer occupations will be truncated, followed by the ellipsis (...). I truncated occupations >= 13 characters long, although you may choose a different value. The point is that you have to have a cut off.

This is the first of many instances where you will want to utilize an overloaded version of ToString that takes a string argument. This can allow you to provide the various formats you'd like to use depending on which container you're presenting in. For example, ToString("ListBox"). This isn't a requirement, but it's certainly one of the better ways to achieve this functionality, in my opinion.

Properties are going to be displayed with a right-alignment. Apartments will have their Unit value displayed after a single # symbol. For-sale properties will be displayed with some kind of special character. I use (and specifically define) the * character to denote for-sale properites, but you're welcome to use variants as much as you like. Heck, you can even go wild and use the full-range of Unicode values available to us when manipulating strings. Donate for-sale properties with emoji's! Just try to include an annotation explaining what that symbol is meant to represent, as I do within the Label just above this ListBox .

Community

Selecting one of the Community RadioButtons is typically the first step to using this application. It should trigger a population of residents who live in that community being displayed, as well as properties within that community. Remember: this, as well as most every other action a user can take when interacting with this program, should come with feedback. That's the Golden Rule of GUI applications. For this assignment, most of the feedback will come in the form of text in the RichTextBox I have spanning the bottom of my Form.

Person/Properties

Selecting one of the Persons listed should detail information about them, similar to what we saw in the output from Assignment 1. Including a list of every residence they reside at. The output from selecting a Person is expected to only persist as long as until the user makes another action. So if I alternate between selecting a Person and a Property, the output should simply alternate between the two.

Toggle For Sale

This Button should only function when a Property has been selected. If not, produce an error or failure message as appropriate. It's also a good idea to specify why something failed, too. So that the user has the information necessary to correct their interactions with the application to get the intended results. As you should expect, this should make the annotation symbol disappear/reappear when toggled. Obviously, the corresponding Property object should have that boolean value toggled as well.

Buy Property

This Button should only function when both a Person and Property are selected. The intended effect should be to have the selected person become the new Owner of the selected Property. This should fail if (1) the selected Property isn't listed for-sale or (2) if the selected Person is already the owner.

Add/Remove Resident

Similar to when we are buying properties, these should have the effect of adding/removing people as residents from properties. Adding should fail if the Person already resides at this Residence; removing should fail if the Person doesn't already reside at this Residence. Basic expectations.

Add New Resident

This input form has four parts to it, each of which have to be well-defined by the user in order to add a new Person to the selected Community. The name input field must have a space character separating the intended first and last name (in that order). No restriction on Occupation. Birthdays are only valid if they are on the current date or previous ones — selecting a birthday in the future should generate an error message. Selecting an invalid residence (such as the "Houses:" label) should also generate an error message. And be aware: the current sort criteria for Persons is based only on first/last names, so attempting to add another Hannibal Lecter to the DeKalb community will fail. Or worse, crash the program, so it'd be worth the effort to check what exception is generated by the Add method of SortedSet Collections and respond accordingly.

Successfully adding a Resident to this community should reset this input form.

Add New Property

This input form has multiple parts, some of which disappear/appear based on which type of Property is being added. Since the NumericUpDowns (what a name...) all have valid initial values defined for them, you can quickly add a House by simply providing a valid Street Address. The square footage should range between [500, 10,000], and increment by 100. The other three should range between [1, 10] and increment by 1 each.

Entering a value into the "Apt. #" TextBox should immediately make invisible the "garage?" CheckBox, as well as disable the NumericUpDown for how many floors there are, setting the value to 1. You can detect when this happens by assigning an Event to the TextChanged EventHandler of this input field. Additionally, if you remove the text from this input field, it should reverse the above affects.

If you check the "garage?" CheckBox, it should only then make visible the next input field: another CheckBox pertaining to whether the garage is attached. Unchecking the "garage?" box should have the reverse affect.

As above when adding new residents, you can run into problems if you (or the TA) were to attempt to add a new Property with the exact same location information of an existing Property in this community. So check yourself, 'fore you wreck yourself.

Successfully adding a Property to this community should reset this input form.

Development Strategies

Much of what you're doing to write in Form1.cs will be the Events attached to the various components in your Form. This drive what responses your application will happen whenever the user does something. I also built 6-7 utility methods for reoccuring necessities in this project, such as refreshing the ListBox containing my properties (to reflect changing their for-sale status or when adding new properties), or validating user input.

There are parts of this project that need to be finished in sequence, before working on other parts, so keep that in mind when dividing up work with your programming partner. The first steps most likely should be correctly displaying the Residents and Properties after selecting a Community RadioButton . Once you have this set up, then you should be able to start splitting the work. Add/Remove Resident both use similar tools, and Buy Property/Toggle For-Sale both use similar tools as well, so dividing the work in that way should be most efficient.

Sample Output

Note: This does not represent every interaction the user may take, but it does cover most of them.

Selecting a Community
Selecting Sycamore's Mayor, Alan Turing. Note his dual residence.
Selecting a Residence
Listing 8768 Pinecrest Rd. for sale
Alan Turing then buying that property.
Confirmation of the new Owner
Failing to buy a not-ForSale property
Failing to buy an already owned property
Alan Turing moving into 8768 Pinecrest Rd.
Confirmation of new residency
Failing to move into already residing residence
Alan Turing moving out of 8768 Pinecrest Rd. (see his TwitLonger for an explanation. Major drama!)
Confirmation of vacancy
Failing to move out of residence, where he doesn't reside

Adding a New Resident:
Before specifying a Community
After
Didn't provide a name
Didn't provide an occupation
Birthday in the future?
Didn't specify a residence
Success!
Residence confirmation

Adding a New Property:
Adding in 1122 Slacker Rd. Because I haven't shoe-horned Slacker into this assignment yet.
Viewing the new Property. Note: There is no Owner, and the Property is listed as For-Sale. This is default.
Specifying a new Apartment
Seeing the new Apartment being listed
The only time you should see the AttachedGarage checkbox