Click here to Skip to main content
15,744,817 members
Articles / Programming Languages / XML
Tip/Trick
Posted 15 Jun 2021

Tagged as

Stats

5.9K views
107 downloads
12 bookmarked

XML Application Settings

Rate me:
Please Sign up or sign in to vote.
2.60/5 (5 votes)
15 Jun 2021CPOL3 min read
Save and retrieve user settings for your application in an XML file
This tip demonstrates the use of a class library for saving and retrieving data from an XML file.

article

Introduction

This tip will demonstrate the use of a simple static class library for saving and retrieving user settings data within an XML file. The image above is the XML file content format; a single node deep structure for storing key/value pairs.

Implementation

C#
//
// Specify settings and initial values
//---------------------------------------------------------

StringCollection settings = new StringCollection();

// First value = Setting name
// Second value = Initial value
// Values are separated with a comma

settings.Add("BorderNone,True");
settings.Add("BorderSingle,False");
settings.Add("Border3D,False");
settings.Add("PictureBoxBackColor,#F0F0F0");

XMLSettings.AppSettingsFile = "Settings.xml"; // Set the file path
XMLSettings.InitializeSettings(settings);     // Create file and set initial values

//----------------------------------------------------------

// Read settings values

rbNone.Checked = bool.Parse(XMLSettings.GetSettingsValue("BorderNone"));
rbBorderSingle.Checked = bool.Parse(XMLSettings.GetSettingsValue("BorderSingle"));
rbBorder3D.Checked = bool.Parse(XMLSettings.GetSettingsValue("Border3D"));
txtColor.Text = XMLSettings.GetSettingsValue("PictureBoxBackColor");

// Set settings values

XMLSettings.SetSettingsValue("BorderNone", rbNone.Checked.ToString());
XMLSettings.SetSettingsValue("BorderSingle", rbBorderSingle.Checked.ToString());
XMLSettings.SetSettingsValue("Border3D", rbBorder3D.Checked.ToString());
XMLSettings.SetSettingsValue("PictureBoxBackColor", txtColor.Text);

Basic Principles

There are three methods and a string that you will use below.

Specify where you want the settings file to be saved for your application.

C#
public static string AppSettingsFile

InitializeSettings() takes a StringCollection object, creates the settings file in the location specified and adds the settings with their initial values.

C#
public static void InitializeSettings(StringCollection _AppSettings)

Specify the setting you want to update and its new value.

C#
public static void SetSettingsValue(string _Field, string _Value)

Retrieve a specific setting and its current value.

C#
public static string GetSettingsValue(string _Field)

Under the Hood

All code exists in XMLSettings.cs. It utilizes the System.Xml, and System.Collections.Specialized namespaces.

Starting at the top of the file...

SettingsFileExists

SettingsFileExists() is a simple helper method for checking whether the settings file already exists. Used in InitializeSettings().

C#
private static bool SettingsFileExists()
{
      bool flag = false;

      if (File.Exists(AppSettingsFile))
            flag = true;
      else
            flag = false;

      return flag;
}

GetSettingsValue

GetSettingsValue() utilizes the XmlDocument object to load the contents of the file. Once the file is loaded, we use the XmlNode object and the SelectSingleNode() method to locate the setting that we want to read the value of. The InnerText property of the XmlNode object is used to retrieve the value of the specifed setting.

C#
public static string GetSettingsValue(string _Field)
{
      XmlDocument doc = new XmlDocument();
      doc.Load(AppSettingsFile);

      XmlNode node = null;
      node = doc.SelectSingleNode("//Settings/" + _Field);

      string value = string.Empty;

      if (node == null)
            value = string.Empty;
      else
            value = node.InnerText;

      return value;
}

SetSettingsValue

As with GetSettingsValue() above, SetSettingsValue() loads the contents of the file. We then attempt to select an XmlNode from the document. If none exist with the name provided, we create a new setting with the XmlDocument.CreateElement() method and add it to the file with XmlDocument.DocumentElement.AppendChild(). Once the setting has been added, we then Save() the document. If an XmlNode with the name provided does exist, we just assign a new value to the InnerText property and then Save() the document.

C#
public static void SetSettingsValue(string _Field, string _Value)
{
      XmlDocument doc = new XmlDocument();
      doc.Load(AppSettingsFile);

      _Field = "//Settings/" + _Field;

      if (doc.SelectSingleNode(_Field) == null)
      {
            _Field = _Field.Replace("//Settings/", "");
            XmlNode field = doc.CreateElement(_Field);
            field.InnerText = _Value;
            doc.DocumentElement.AppendChild(field);
            doc.Save(AppSettingsFile);
      }
      else
      {
            XmlNode node = null;
            node = doc.SelectSingleNode(_Field);
            node.InnerText = _Value;
            doc.Save(AppSettingsFile);
      }
}

InitializeSettings

InitializeSettings() does a few basic things. First, it checks whether or not the settings file exists. If it does not, it will create the file, loop through all the settings in the StringCollection and add them to the file. If the file does exist, it will check to see if there have been any new settings added to the StringCollection, and add the ones that don't exist in the file and set the initial value.

C#
public static void InitializeSettings(StringCollection _AppSettings)
{
    if (!SettingsFileExists())
    {
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        XmlWriter XmlWrt = XmlWriter.Create(AppSettingsFile, settings);

        {
            var withBlock = XmlWrt;
            withBlock.WriteStartDocument();

            withBlock.WriteComment("Application Settings");
            withBlock.WriteStartElement("Settings");

            string[] arr;

            foreach (string setting in _AppSettings)
            {
                arr = setting.Split(',');

                string settingName = arr[0];
                string defaultValue = arr[1];

                withBlock.WriteStartElement(settingName);
                withBlock.WriteString(defaultValue);
                withBlock.WriteEndElement();
            }

            withBlock.WriteEndDocument();
            withBlock.Close();
        }

        XmlWrt = null;
    }
    else
    {
        XmlDocument xmlDoc = new XmlDocument();

        xmlDoc.Load(AppSettingsFile);
        XmlElement elm = xmlDoc.DocumentElement;
        XmlNodeList lstSettings = elm.ChildNodes;
        string[] arr;
        StringCollection nodeNames = new StringCollection();

        foreach (XmlNode node in lstSettings)
        {
            nodeNames.Add(node.Name);
        }

        foreach (string setting in _AppSettings)
        {
            arr = setting.Split(',');

            string settingName = arr[0];
            string defaultValue = arr[1];

            if (!nodeNames.Contains(settingName))
            {
                XmlNode newSetting = xmlDoc.CreateElement(settingName);
                newSetting.InnerText = defaultValue;
                xmlDoc.DocumentElement.AppendChild(newSetting);
                xmlDoc.Save(AppSettingsFile);
            }
        }
    }
}

Conclusion

I wanted to write a simple class that I could use in my applications to store user settings, however, after using it and writing this article, I would like to improve the following items:

  • Revise code to eliminate using a StringCollection with values separated by a comma. I currently have not run into any issues with the implementation considering I have always hand coded these values, however handling commas can be a hassle. I will explore using a Dictionary. Recommendations are welcome in the comments.
  • Figure out a way to dynamically create an enum based on the settings that are in the file to eliminate potential errors due to spelling mistakes. Perhaps a Dictionary will also help with this.

Comments and recommendations for improvement are welcome. Thanks for reading!

History

  • 15th June, 2021: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
Self taught hobbyist programmer Smile | :)

Comments and Discussions

 
GeneralMy vote of 2 Pin
BillWoodruff22-Jun-21 18:14
professionalBillWoodruff22-Jun-21 18:14 
GeneralRe: My vote of 2 Pin
chris_mackay27-Mar-23 14:57
chris_mackay27-Mar-23 14:57 
I appreciate your comment. I have since been utilizing existing packages and libraries which have made my life a lot easier and my projects much better. Smile | :)
QuestionApp.config Pin
dmjm-h16-Jun-21 9:50
dmjm-h16-Jun-21 9:50 
AnswerRe: App.config Pin
chris_mackay18-Jun-21 18:56
chris_mackay18-Jun-21 18:56 
QuestionMessage Closed Pin
16-Jun-21 8:10
professionalRITECH Vietnam16-Jun-21 8:10 
GeneralMy vote of 3 Pin
Vincent Radio16-Jun-21 7:25
professionalVincent Radio16-Jun-21 7:25 
SuggestionAn easier way Pin
johnybe7516-Jun-21 5:29
johnybe7516-Jun-21 5:29 
GeneralRe: An easier way Pin
chris_mackay18-Jun-21 15:31
chris_mackay18-Jun-21 15:31 
GeneralMy vote of 5 Pin
Vincent Radio15-Jun-21 20:19
professionalVincent Radio15-Jun-21 20:19 
Answer15248996 Pin
Member 1524899615-Jun-21 18:23
Member 1524899615-Jun-21 18:23 
Answer15248996 Pin
Member 1524899615-Jun-21 18:23
Member 1524899615-Jun-21 18:23 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.