Creating a Dynamic Configuration Dialog in C# and .NET

This article will show you how to create a configuration dialog that builds itself from the existing application configuration name-value pairs contained in the appSettings of the app.config file.

DynamicConfigDialog.jpg

Figure 1 - Dynamic Configuration Dialog

Introduction

I often find myself using the app.config file for storing name-value pairs to be used as configuration parameters for my application. It suddenly dawned on me that wouldn't it be nice if I could create a dynamic dialog from these name-value pairs so that I could edit my configuration inside my application? Yes it would! Thus I created the Dynamic Configuration Dialog. Without writing a line of code, you can allow the user of your app to edit any of the name value pairs listed in the appSettings section of your configuration file.

Design

The design of the dynamic app configuration dialog consists of three classes: The AppConfigDialog that displays the name value pairs to the user, the ConfigReaderWriter that performs all the file reading and writing on the myapp.exe.config file, and the FieldFactory used to create the dynamic  label and textbox controls for the name value pairs to edit. When the AppConfigDialog is constructed, it reads each name-value pair in the app.config file and uses the FieldFactory to create the corresponding controls. After the user edits the AppConfigDialog with new configuration settings and clicks OK, the ConfigReaderWriter is used to write out the new configuration settings from the dialog.

DynamicConfigDialogUML.jpg

Figure 2 - UML Design of the Dynamic Configuration Dialog Reverse engineered using the WithClass UML Tool

The Code

As described in the design section, the Dynamic Dialog is created in the constructor of the AppConfigDialog class as shown in Listing 1. After all the existing controls in the dialog are initialized, the configuration file is read and the edit fields of the dialog are dynamically created with the FieldFactory. After all the controls are created in the dialog, the dialog is stretched vertically to fit the additional controls to the dialog, and the okay and cancel button are shifted down to the bottom of the dialog.

Listing 1 - Creating the Dynamic Application Configuration Dialog

      public AppConfigDialog()
            {
                 
//
                 
// Required for Windows Form Designer support
                 
//
                  InitializeComponent();
                  // create a field factory for populating dialog
                  _fieldFactory = new FieldFactory(this);  
                  // set the configuration path based on the location of the executing assembly
                  ConfigReaderWriter.SetConfigPath(); 
                   // get the configuration settings
                  Hashtable configurationSettings = ConfigReaderWriter.GetConfigSettings();
                // create dialog controls for each name-value pair in the configuration file
                  CreateDynamicFieldsForDialog(configurationSettings); 
                  // adjust the length of the dialog to fit all the fields
                  AdjustDialogLength();
            }
            /// <summary>
            ///
Cycle through all application settings and create fields
            ///
using the field factory
            ///
</summary>
            void CreateDynamicFieldsForDialog(Hashtable configurationSettings)
            {
                 
// Create a label and corresponding text box for each name-value pair
                  foreach (string key in configurationSettings.Keys)
                  {
                        _fieldFactory.CreateLabel(key);
                        _fieldFactory.CreateTextBox(key, configurationSettings[key] as string);
                        _fieldFactory.IncrementVerticalPosition();
                  }
            }
            void AdjustDialogLength()
            {
                  _fieldFactory.IncrementVerticalPosition();
                 
// increase dialog size to vertical position + button height + 5
                  SetBounds(Left, Top, ClientRectangle.Width, _fieldFactory.VerticalPosition + btnOK.Height + 10);
                  btnOK.Location = new Point(btnOK.Location.X, _fieldFactory.VerticalPosition - (btnOK.Height + 10));
                  btnCancel.Location = new Point(btnCancel.Location.X, _fieldFactory.VerticalPosition -
                        (btnOK.Height + 10));
            } 

When we are ready to save the configuration file(after we made a change in the dialog), we use the ConfigReaderWriter class's replaceConfigSettings method. This method will alllow us to save the new changes to a name-value pair made inside the dialog. Since the configuration file is an XML file, we can load it into an XmlDocument. Then we use XPath on the XmlDocument to find the node containing the key-value pair that we want to change. Once we found the correct node, we simply set the new value and resave the configuration file as shown in listing 2:

Listing 2 - Replacing the key-value pair in the configuration file and saving it

            /// <summary>
            ///
Replace the key and value pair in the configuration file and save it
            ///
</summary>
            ///
<param name="key"></param>
            /// <param name="val"></param>
            static public void replaceConfigSettings(string key, string val)
            {
                  XmlDocument xDoc = new XmlDocument();
                  string sFileName = _configurationPath;
                 
try
                  {
                       
// load the configuration file
                       xDoc.Load(sFileName);
                        // find the node of interest containing the key using XPATH
                        XmlNode theNode = xDoc.SelectSingleNode(@"/configuration/appSettings/add[@key = '" + key + "\']"); 
                        // Set the new value for the node
                        if (theNode != null)
                             theNode.Attributes["value"].Value = val;
                        // lop off file prefix of the filename if it exists
                        if(sFileName.StartsWith("file:///"))
                              sFileName = sFileName.Remove(0,8);
                        // save the new configuration settings
                        xDoc.Save(sFileName);
                        xDoc = null;
                  }
                  catch(Exception ex)
                  {

                        System.Windows.Forms.MessageBox.Show("replaceConfigSettings()"+ex.Message);
                        xDoc = null;
                  }
            }

Usage

It's easy to use the dynamic configuration dialog. You simply construct it and show it. The internal classes and methods described above do the rest.

Listing 3 - Using the Dynamic Configuration Dialog

          private void button1_Click(object sender, System.EventArgs e)
            {
                 
// construct the dynamic configuration dialog
                  AppConfigDialog dialog = new AppConfigDialog(); 
                 
// show it to the user so they can edit the
                 
// configuration file
                  dialog.ShowDialog();
            }

Conclusion

Sometimes its nice to have some reusable GUI controls in your programming arsenal. This simple control will give your user the power to edit any standard configuration file containing name-value pairs by dynamically building a dialog from the appSettings in the file. This way it is more a-pair-ent to your user on how to edit their preferences with the help of C# and .NET.