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.
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:
- 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
- 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
- List addresses of all for-sale properties — this will be realized by annotations next to each property
in the ListBox
- List all residents of a community — similar to Full Property List
- List all residents of a property, by street address — this is achieved when the user selects a
property from the ListBox
- Toggle a property, by street address, as being for-sale or not. — we'll include a
Button for this
- Buy a for-sale property, by street address — Button for this, too
- Add yourself as an occupant to a property. — It's Button-o clock
- Remove yourself as an occupant from a property — rather than take your rear off, you're going to put
your ButtOn
- 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