Exploring the TypingBuddy Application (Part 7)

In the previous post, Exploring the TypingBuddy Application (Part 6), you learned how the user can create custom messages for TypingBuddy. These messages make it possible for TypingBuddy to suggest activities that interest the user. The form used for this activity, frmAddEdit, can display a single message at a time for either adding or editing a message. The focus of this week’s post, frmMessages, makes it possible to manage the list of configured messages, as well as add new ones. It provides access to the functionality required to add, edit, and delete messages as shown here.

TypingBuddy0701

The setup required to create this form appears in the Exploring the TypingBuddy Application (Part 3) post. Before this form can do anything else, it must have a copy of the current message list. It uses this list to populate the Messages list box when the form loads. Here’s the code needed to perform this task:

// Create a copy of the database.
TBMessages Settings;
 
private void frmMessages_Load(object sender, EventArgs e)
{
   // Initialize the settings.
   Settings = TBMessages.LoadSettings();
 
   // Determine if there are any messages to load.
   if (Settings.MessageList != null)
 
      // If there are messages to process, check them one at a time.
      foreach (TBMessage ThisMessage in Settings.MessageList)
 
         // Display just the title in the listbox.
         lstMessages.Items.Add(ThisMessage.Title);
}

The example begins by creating a TBMessages object, Settings, to hold the list of messages along with the other settings used by the application. In frmMessages_Load(), the application instantiates this object by calling TBMessages.LoadSettings(). When Settings contains one or more TBMessage entries, the application loads them into lstMessages so that the user can see them immediately after the form loads.

The form contains four buttons. The code for Close is very simple—all it does is pass back a DialogResult value of Cancel. The Add button is a little more complex as shown here:

private void btnAdd_Click(object sender, EventArgs e)
{
   // Create the required form.
   frmAddEdit AddMessage = new frmAddEdit();
 
   // Provide the required resources.
   if (Settings.MessageList != null)
      AddMessage.MessageList = Settings.MessageList;
 
   // Display the form.
   if (AddMessage.ShowDialog(this) == DialogResult.OK)
   {
      // Retrieve the new settings.
      Settings.MessageList = AddMessage.MessageList;
 
      // Save the settings.
      TBMessages.SaveSettings(Settings);
   }
 
   // Clear the message list.
   lstMessages.Items.Clear();
 
   // Determine if there are any messages to load.
   if (Settings.MessageList != null)
 
      // If there are messages to process, check them one at a time.
      foreach (TBMessage ThisMessage in Settings.MessageList)
 
         // Display just the title in the listbox.
         lstMessages.Items.Add(ThisMessage.Title);
}

The code begins by creating a frmAddEdit object, AddMessage. It then passes the current list of messages to AddMessage and displays the form on screen where the user will provide values for a new message. When the return value is DialogResult.OK, the code retrieves the updated list of messages and places them in Settings.MessageList. The code then saves the new list of messages to disk.

At this point, the code must update the user’s view of the messages. It does this by calling lstMessages.Items.Clear() first to clear any existing messages. When Settings.MessageList contains messages (it may not because the user may have chosen to click Cancel instead of adding a message), the code adds each of the message titles to lstMessages.

The Edit button is the most complex of the four buttons. It not only must choose which message to edit, but it must also configure the frmAddEdit object to display a message editing dialog box, rather than a message adding dialog box. Of course, this event handler will also need to perform all of the tasks performed when adding a new message. Here’s the code you use to perform these tasks.

private void btnEdit_Click(object sender, EventArgs e)
{
   // Create the required form.
   frmAddEdit AddMessage = new frmAddEdit();
 
   // Configure the form.
   AddMessage.Text = "Edit Existing Message";
   AddMessage.btnAdd.Text = "&Edit";
   AddMessage.btnAdd.AccessibleDescription =
      "Edits an existing item in the list.";
   AddMessage.toolTip1.SetToolTip(AddMessage.btnAdd,
      "Edits an existing item in the list.");
 
   // Set up for an edit.
   AddMessage.IsEdit = true;
 
   // Make sure there are records to edit.
   if (Settings.MessageList != null)
   {
      // Provide the required resources.
      AddMessage.MessageList = Settings.MessageList;
 
      // Set the record number.
      AddMessage.RecordNumber = lstMessages.SelectedIndex;
   }
   else
   {
      // Display a message and exit when there are no records to edit.
      MessageBox.Show(
         "There are no messages to edit!",
         "Editing Error",
         MessageBoxButtons.OK,
         MessageBoxIcon.Error);
      return;
   }
 
   // Make sure the user has selected an item to edit.
   if (lstMessages.SelectedIndex == -1)
   {
      // Display a message and exit when there are no records to edit.
      MessageBox.Show(
         "You must select a message to edit!",
         "Selection Error",
         MessageBoxButtons.OK,
         MessageBoxIcon.Error);
      return;
   }
 
   // Display the form.
   if (AddMessage.ShowDialog(this) == DialogResult.OK)
   {
      // Retrieve the new settings.
      Settings.MessageList = AddMessage.MessageList;
 
      // Save the settings.
      TBMessages.SaveSettings(Settings);
   }
 
   // Clear the message list.
   lstMessages.Items.Clear();
 
   // Determine if there are any messages to load.
   if (Settings.MessageList != null)
 
      // If there are messages to process, check them one at a time.
      foreach (TBMessage ThisMessage in Settings.MessageList)
 
         // Display just the title in the listbox.
         lstMessages.Items.Add(ThisMessage.Title);
}

This part of the example begins by creating a frmAddEdit object, AddMessage (I simply recycled the name from the previous event handler). The first two changes configure the form so that the user sees the right messages. However, because we’re also focusing on accessibility in this example, the application must also change the settings that affect accessibility. For example, this changes would modify what a user hears through a screen reader. When making your application accessibility friendly, you need to keep these sorts of changes in mind.

Because the application is editing an existing message, rather than editing an existing message, it must also set AddMessage.IsEdit to true. As mentioned in the previous posting, this setting affects how the form reacts to user input and also controls initial configuration.

At this point, the application must pass the list of messages along to AddMessage, just as it did when adding a new message. However, notice the error trapping code that is added in this case. For example, you can add a message when the message list is null, but you can edit a message that doesn’t exist. Likewise, a user must actually select a message in the list in order to edit it—you can’t simply assume which message the user intended to edit.

Only after the conditions are right can the application display the editing dialog box. When the user makes changes and clicks Edit, the application updates the message list and updates the list of messages, just as it does when adding a new message.

The Delete button is unique in that it does change the message list, but it doesn’t rely on frmAddEdit to do it. All that really needs to happen is that the application removes the required record from the message database as shown here:

private void btnDelete_Click(object sender, EventArgs e)
{
   // Make sure the user has selected an item to edit.
   if (lstMessages.SelectedIndex == -1)
   {
      // Display a message and exit when
      // the user hasn't selected a record.
      MessageBox.Show(
         "You must select a message to edit!",
         "Selection Error",
         MessageBoxButtons.OK,
         MessageBoxIcon.Error);
      return;
   }
 
   // Create a temporary message database.
   TBMessage[] Temp = new TBMessage[Settings.MessageList.Length - 1];
 
   // Create a counter for the temporary database.
   Int32 Count = 0;
 
   // Check each of the records for the defined message and delete
   // the selected message by not copying it to the message list.
   foreach (TBMessage ThisMessage in Settings.MessageList)
      if (ThisMessage.Title != (String)lstMessages.SelectedItem)
      {
         // Copy the record.
         Temp[Count] = ThisMessage;
 
         // Update the counter.
         Count++;
      }
 
   // Update the settings.
   Settings.MessageList = Temp;
    
   // Save the new message list.
   TBMessages.SaveSettings(Settings);
 
   // Update the message list.
   lstMessages.Items.RemoveAt(lstMessages.SelectedIndex);
}

The main requirement that the application must adhere to in this case is that the user must select a record to delete. Again, the application can’t assume anything about what the user really intended to do. Good design practices dictate that you make this check and then ask the user to make a selection when there isn’t any selection.

There are many different methods you can use to delete a record from MessageList. The example chooses to use a simple approach that works quite fast. It simply creates a temporary list of messages, Temp, of type TBMessage[] that contains one less record than the original array. It then copies all of the original records to the temporary array, except for the one record that matches the one that the user has selected. After it completes the copying process, the application saves the message list and updates lstMessages so the user sees that the entry is deleted.

We’ve moved up to frmMain. This particular form will require a little more work than you’ve done so far because it’s the focal point of everything that TypingBuddy does. Next week we’ll start a series of posts about frmMain. In the meantime, let me know if you have any questions at John@JohnMuellerBooks.com. You can see the next post in this series at Exploring the TypingBuddy Application (Part 8).