REAL-WORLD COMPUTER PROGRAMMING FOR KIDS
STEP 18: EXTREME MAKEOVER OF THE FORM and BEGINNING of REFACTORING THE CODE
In Step 17, we took a little detour to talk about Exceptions, “try...catch” blocks, and “try...finally” blocks.
Now we will get back to the Multiple Choice code we’ve been working on revamping, or “Refactoring,” as programmers call it. We could also call it rejuvenating, revivifying, recombobulating, etc. Anyway, we will update our app, retrofitting it to use any set of multiple choice questions we give it.
In previous Steps, we created a couple of CSV files with questions and answers to test with, and learned how to load them into our app. Now we will make the necessary changes to the form to accommodate this new functionality.
First, we will do some dreary and drab and somewhat tedious (but necessary!) “housekeeping” work on the Form as the first step in the makeover of how the app looks and runs. Unfortunately, you see, not all of programming is fun and games. There’s a little bit of “grunt work” from time to time. The good news: performing this type of activity builds character! Or something like that.

Anyway, I’m trusting you to be able to accomplish the following steps by clicking the Controls in turn, and then using Visual Studio’s Properties pane to make these beautifications. Get ready! Brace up! These are the tough and tedious tasks (well, kind of tedious, anyway):
0) First (or Zeroeth), make sure you’re looking at the Form (on the Form1.cs [Designer] tab) in Visual Studio.
1) Change the name of the Label at the top of the form (which is probably still named “label1”) to “lblQuestion”
2) Change the Text in that Label to “The Question Will Appear Here after you Select a File” (or something similar – it will get replaced at run time, anyway)
3) Change the GroupBox’s Text property from “groupbox1” to “Make a Selection ”
4) Change the Text properties of the Radio Buttons to “Candidate Answer 1”, “Candidate Answer 2”, and “Candidate Answer 3.”
5) Change the Text of the NYNO label (lblNYNO) to “%” and change its name to “lblPercentage”
We will keep the running percentage of correct answers there (in that label), updating it after each click of the “Next” button.
6) Change the Text of the lblMorphable Label from “Question N of 10” to “Question N of N”
This is because the CSV files we load may have more (or less) than 10 questions. This is because you may want to create your own CSV files with Questions and Answers you have come up with, and I don’t want to limit you to a certain number of questions.
7) Change the Name property of lblMorphable to lblQuestionNOfN
Remember, “N” stands for an unknown number, so “N of N” can mean “1 of 10” or “3 of 10” or “7 of 3,142” or just about anything else.
8) Make the “Show Score” button invisible. Or, you could simply get rid of it (delete it) by selecting it and hitting the Delete key.
9) On a similar note, do the same with lblGeezer – either make it invisible, or delete it.
10) Change the Text of the Form itself from “Guess Your Age” to whatever you want it to be. “Guess Your Age” will no longer be appropriate (although the name of the app itself will stay the same; truth be told, we should have named it something else, instead of being so specific about what the app was going to do – guess ages and nothing else).
Personally, I changed the Form’s Text to “Exercise Your Cranium”
Here’s how the Form now looks at Design Time:

Now for the parts of the code we have to change:
10) Go to the code tab (Form1.cs)
11) Try to build the app (by simultaneously pressing Ctrl+Shift+B on the keyboard or selecting Build > Build Solution using the Visual Studio menu, or Build > Rebuild). It will fail, because we “moved the Form’s cheese” (changed the names of some things, and deleted other things).

So let’s take care of these errors, or “squash these bugs.”
We’ll do them together, one at a time.
The first error is, “The name ‘btnShowScore’ does not exist in the current context”
2-click that error message, and it takes you right to that spot:
btnShowScore.Enabled = true;
We see that this is located within the SwapModes() method. Since we won’t be swapping modes anymore, comment that entire method out. Do the same with the CalculateAgeRange() method. It should then look like this:

Note: A shortcut to “comment out” a line of code (or a section of code) is to put your cursor at the beginning of the line (or select the entire block that you want to comment out) and then simultaneously press Ctrl+K+C. To uncomment an already commented section, use Ctrl+K+U.
Commenting out those methods takes care of some of the error messages, but brings up some others. Specifically, there are now three new error messages. These have sprung up because the calls to those commented-out methods are now whining (or whinging), “I can’t see the SwapModes() method! Ahhhh!!!!” and, “I can’t see the CalculateAgeAndDisplay() method! Boo hoo hoo!”
The first error message says, “The name ‘SwapModes’ does not exist in the current context.” 2-click that error message. Doing so takes us to the event handler named button1_Click(). But looking at it, we see that really practically the entire logic (code) needs to change.
Before diving into that, though, let’s rename the generic name “button1” by going back to the Designer tab and changing it from that (“button1”) to “btnNext.”
Good. Now comment out everything between the curly braces in the button’s event handler.
What do we want the code there to be now?
It will be much simplified – at least this part of it. Just type LoadNextBatch(); into the code area of the button1_Click() event handler. We will have to revisit (refactor) that code next.
First, though, let’s see if the app will build now. Try to build it again (Ctrl+Shift+B or etc.). This time the only error message should be:
The name ‘CalculateAgeAndDisplay’ does not exist in the current context
Click the error message to go there; you’ll see that it’s in the btnShowScore_Click() event handler. Since we won’t be showing a score at the end anymore, comment out that entire block of code, too.
Now again try to compile (or build) the app. This time it should work.
Run the app (by pressing the F5 key or selecting Debug > Start Debugging from the menu bar). Now that it’s compiling again, here’s what the Form looks like at Runtime:

That’s more like it! That’s what I’m writin’ about! That’s just what the nurse ordered! Let’s get to work on the code in the LoadNextBatch() method now.
Note: When you are ready to stop the app in Visual Studio, you can press Shift+F5 to go back to “coding mode.”
The first part of the code in LoadNextBatch() should now look like this:
MultipleChoiceClassIndex++;
freezeAnswer = MultipleChoiceClassIndex + 1 == numberOfQuestions;
btnNext.Enabled = false;
radioButton1.Checked = false;
radioButton2.Checked = false;
radioButton3.Checked = false;
In connection with the above, if it’s not already there, add this to the global variable declarations at the top of the form:
bool freezeAnswer = false;
Put all of the code after that in a try...catch block like the one shown in Step 17, and as shown below.
Although this part -- right after the “try {” -- will stay the same:
UpdateQuestionNumberLabel();
if (progressBar1.Value < progressBar1.Maximum)
{
progressBar1.Value = progressBar1.Value + stepAmount;
}
...the related “stepAmount” code needs to change, because the stepAmount (how far to move the colored part of the ProgressBar after each question) will vary depending on how many questions there are. Currently the stepAmount variable is defined this way:
int stepAmount = 10;
This is no longer valid. It was when we knew there would be 10 questions, but not anymore. So change it to this:
int stepAmount = 0;
We will change the number assigned to it again to whatever’s right later, in the cmbxSelectMultiChoiceFile_SelectedIndexChanged() event handler (based on the number of questions the CSV file we load contains).
Let’s do that now. As was just mentioned, to figure out what the value of stepAmount should be, we need to determine how many questions there are. We can do that with the following code (note the bolded parts):
private void cmbxSelectMultiChoiceFile_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedFile = string.Empty;
string[] fileStrArray;
MultipleChoiceClass mcc;
mccList = new List<MultipleChoiceClass>();
int numberOfQuestions = 0;
double stepPercentage = 0.0;
const int QUESTION = 0;
const int CANDIDATEANSWER1 = 1;
const int CANDIDATEANSWER2 = 2;
const int CANDIDATEANSWER3 = 3;
// The first time this event handler is triggered, mccList will be null
if (mccList is null)
{
mccList = new List<MultipleChoiceClass>();
}
else // subsequent times this event handler is triggered, clear it
{
mccList.Clear(); // any previous questions/answers are removed
}
selectedFile = cmbxSelectMultiChoiceFile.SelectedItem.ToString();
try
{
fileStrArray = File.ReadAllLines(selectedFile, Encoding.UTF8);
numberOfQuestions = fileStrArray.Length;
stepPercentage = 100 / numberOfQuestions;
stepAmount = (int)Math.Round(stepPercentage);
foreach (string line in fileStrArray)
{
string[] subPhrases = line.Split(',');
mcc = new MultipleChoiceClass();
mcc.Question = subPhrases[QUESTION];
mcc.CandidateAnswer1 = subPhrases[CANDIDATEANSWER1];
mcc.CandidateAnswer2 = subPhrases[CANDIDATEANSWER2];
mcc.CandidateAnswer3 = subPhrases[CANDIDATEANSWER3];
if (mcc.CandidateAnswer1.Contains("*"))
{
mcc.CorrectAnswer = 1;
mcc.CandidateAnswer1 = mcc.CandidateAnswer1.Substring(1);
}
else if(mcc.CandidateAnswer2.Contains("*"))
{
mcc.CorrectAnswer = 2;
mcc.CandidateAnswer2 = mcc.CandidateAnswer2.Substring(1);
}
else if (mcc.CandidateAnswer3.Contains("*"))
{
mcc.CorrectAnswer = 3;
mcc.CandidateAnswer3 = mcc.CandidateAnswer3.Substring(1);
}
mccList.Add(mcc);
}
LoadNextBatch();
} // try
catch (Exception ex)
{
MessageBox.Show(ex.Message);
throw; // Index was outside the bounds of the array
}
}
Note that the LoadNextBatch() method (bolded above) is called after the foreach loop runs. This populates the controls with the first question and set of candidate answers.
Before we forget it, we’d better comment out the variable and const declarations we no longer need at the top of the Form1.cs file, too, like so (or, if you’re feeling brave and brash and bold (no pun intended), just delete all of them):
int sequence = 0;
//int ageScore = 0;
int stepAmount = 10;
//bool InProgressMode = true;
List<MultipleChoiceClass> mccList;
//const int WHIPPERSNAPPER = 0;
//const int NYNO = 1;
//const int GEEZER = 2;
This wreaks all sorts of havoc, though, because those things we just commented out or callously relegated to the ash-heap of history are referenced all throughout the code. We must comment out all the places where they occur in order to silence those 30 sirens that are going off (figuratively speaking). That is to say, there are now 30 error messages complaining about these variables and constants being assigned values when, according to the compiler, they don’t even exist (since we commented them out or deleted them, hiding them from the compiler).
But we can take care of this easily enough; in fact, we can do it in “one fell swoop.” Simply comment out everything in the LoadNextBatch() method, starting at this code:
if (sequence == 1)
{
groupBox1.Text = "Select a ROGER";
radioButton1.Text = "EBERT";
radioButton1.Tag = NYNO;
radioButton2.Text = "FEDERER";
radioButton2.Tag = WHIPPERSNAPPER;
radioButton3.Text = "MARIS";
radioButton3.Tag = GEEZER;
}
// similar code elided
...and going through this part:
else if (sequence == 10)
{
groupBox1.Text = "Select a BOY'S NAME";
radioButton1.Text = "HORACE";
radioButton1.Tag = GEEZER;
radioButton2.Text = "JOHN";
radioButton2.Tag = NYNO;
radioButton3.Text = "JOSHUA";
radioButton3.Tag = WHIPPERSNAPPER;
}
In other words, we comment out the entire “if...else” portion of code in that method.
This “hard-coded” stuff that we just commented out will all need to be “made generic” now in our makeover of the form and, more importantly, the code. We have to do this because we won’t know how many questions there will be until run time, nor what the questions and candidate answers will be – it all depends on which file the user chooses from the combo box.
We have accomplished enough for this Step, though; we will continue with the Makeover/Refactoring of the code in the next Step.
Until then!
Earth-shakingly Important Notice: If you have a basic programming question (suitable to an audience of “Kids”), send it to idiolectable@gmail.com, specifying whether you would like your name and location used if it is printed in a future “Step” of this newsletter. If you are a subscriber to the newsletter, you can also leave a question at the bottom of this Step, in the “Comments” section.
If you do not want to give your real name, a nickname is acceptable (the first “Letter to the Editor” of mine that was printed appeared in Rolling Stone magazine, back in the early 1970s, and I signed it “Sylvester” for some reason which I no longer remember).
Finally, it’s always interesting to see where people are from, so please provide your City or Town and the State it’s in, too (or Province, or whatever the region where you live is called).
To listen to this Step, the audio of it can be found here: