Exploring the TimeCheck Application (Part 10)

Last week you learned about the remaining major elements of the GroupSettings class in the Exploring the TimeCheck Application (Part 9) post. Like many modern applications, you now see how to create an application that relies on both localized user settings (the UserSettings class) and work group-wide settings (the GroupSettings class). Both classes rely on XML data files to create a database of settings that the application relies upon for configuration needs. The use of XML data files makes the application incredibly portable. It’s important to remember the sources of settings information this application:

 

  • The user manually configures some of the settings in the UserSettings class by selecting items such as the default task and project.
  • The administrator manually configures some settings in the UserSettings class by selecting items that only the administrator can see.
  • The application automatically provides default settings in the UserSettings class when the application hasn’t been configured by either the user or the administrator.
  • The administrator manually configures all settings in the GroupSettings class.
  • The application doesn’t automatically supply any defaults for the GroupSettings class and simply displays blank screen areas when there are no values to display.


I wanted to reiterate these settings requirements before moving on because there were some questions on the part of a few readers as to how the settings worked. I’m not showing the security features of this example just yet—for right now, it’s important to focus on the functionality required to perform the desired tasks. However, I do encourage developers creating production applications to include security as part of the application design and development process (as I did when putting this example together). You can’t bolt security on as an afterthought. However, I have chosen to not discuss the security features just now in order to make the example easier to understand.

Because I’m still answering some questions about this application, I’ve decided to keep today’s post simple. Look carefully at frmConfigure (see Exploring the TimeCheck Application (Part 3) for details on the frmConfigure configuration). This form contains two combo boxes and two list boxes that you must fill at various times during the use of the form. For example, you must fill all four of them when initially displaying the data. Any change to the two list boxes must also appear in the two combo boxes. In addition, changes to group data must appear every time the user decides to make any sort of change to the user settings, so you have an opportunity here for interactions between multiple sessions. Because of the potential for problems, the frmConfigure class uses a method named FillList() to fill all four lists any time there is a chance for changes. The following code shows how FillList() works.

private void FillLists()
{
   // Check for a list of tasks.
   if (GroupData.TaskList != null)
 
   // Fill the default and administrator lists with data.
   {
      foreach (Task Item in GroupData.TaskList)
      {
         lstStandardTasks.Items.Add(Item.Name);
         cbWorkType.Items.Add(Item.Name);
      }
   }
 
   // Check for a list of projects.
   if (GroupData.ProjectList != null)
 
   // Fill the default and administrator lists with data.
   {
      foreach (Project Item in GroupData.ProjectList)
      {
         lstStandardProjects.Items.Add(Item.Name);
         cbProjectName.Items.Add(Item.Name);
      }
   }
 
   // Add the "None" entry to the two user lists.
   cbWorkType.Items.Add("None");
   cbProjectName.Items.Add("None");
 
   // Choose the user-supplied default (if any).
   if (UserData.DefaultTask != null)
      cbWorkType.SelectedItem = UserData.DefaultTask;
   if (UserData.DefaultProject != null)
      cbProjectName.SelectedItem = UserData.DefaultProject;
}

Any time there is any change to any of the data that frmConfigure manages, the code calls FillList() to ensure all of the lists are updated. Using a single method like this makes it possible to update the application without any potential problem with method interactions.

In this case, the code works with GroupData.TaskList and GroupData.ProjectList to obtain entries for the two lists associated with a particular data type. The user lists must also contain a None entry, so the code adds this item to the two combo boxes after the lists are filled. Having the None option last helps ensure that the user actually reviews the lists of potential choices before accepting the None option. Using a foreach loop to fill each list is extremely efficient.

The FillList() method must also interact with UserData to automatically choose the user’s selection of a default task and a default project. Remember that the default selection, the one automatically created by the application, is None. When the user hasn’t made a selection, the Configure TimeCheck dialog box displays None for these two entries.

This code provides a subtle form of error handling. Theoretically, GroupData.TaskList, GroupData.ProjectList, UserData.DefaultTask, and UserData.DefaultProject should never be null when this piece of code is called. However, the code makes a quick null check anyway just to ensure it doesn’t attempt to work with a null data value. This quick check will reduce potential errors without affecting performance in any noticeable way. Using this sort of check will help make your applications more robust too.

Well, that’s it for this week. Please keep those questions coming. I realize that this example is a bit more complicated than the ones you’re used to seeing in books, so I want to be sure I don’t leave anyone behind. Be sure to send your questions to me at John@JohnMuellerBooks.com.