Introduction

INI files and the registry are generally things of the past for .NET
applications. But what to use? XML seems appropriate, but one look at
System.XML is enough to scare most developers off, especially just
to store a few fields. Fortunately, there is a very easy way in .NET to solve
this, but one that is usually not seen by developers. In this article, I’ll
explain how you can easily store and retrieve your application settings with
just a few lines of code.

History

In Windows 3.1, developers used INI files to store settings. In general, they
worked pretty well for simple settings, but were not appropriate for more
complex data. INI files also did not account for multiple users, and thus
Microsoft invented the registry.

Along came the registry with Win32. The registry was fast, hierarchical,
multi user, and allowed storage of typed data. But unfortunately, the registry
was a central system component and was not contained as part of the application
install.

Next, XML became popular. XML offers fast, hierarchical storage of typed
data. However, XML is so flexible that for most users doing anything simple is
quite an undertaking. Fortunately, there are easier ways than using
System.XML and handling everything yourself.

Old Ways

Many users have simply resorted to using INI files or the registry. INI files
are not supported in .NET. To use INI files, a developer must call the Win32 API
directly, or use some prepared classes on the Internet that use the Win32 API.
For the registry, classes are available in Microsoft.Win32. XML
however is portable and can be easily edited by end users if necessary.

How

The secret to painless XML settings files is to use a typed
DataSet. A typed DataSet is actually an in memory
dataset for working with ADO.NET, but they have many other uses as well. To add
a typed DataSet to your application, right click on the project in
the Solution Explorer, and select Add New Item. Now select DataSet, and give the
dataset a name.

Now, we have a blank DataSet in our project. For the purposes of
a demo, I have created a main form already that looks like this.

I have chosen these for the demo as they give us three types of data to
store, a string, an integer, and a Boolean. Now, let’s design our
DataSet around these.

Open the Solution Explorer and find the newly created
DataSet.

When you double click on Settings.xsd, you will see a designer like
this:

This is a blank DataSet. A DataSet can contain
several tables, but for this demo, we will add just one. Open the toolbox, and
you will see different items than you normally see in a WinForms or a WebForms
application.

There are a lot of items in the toolbox related to DataSets, but
for the needs of this article, we only need Element. Double click
on Element to add one to the DataSet. The
DataSet should now look like this:

The Element type corresponds to a DataTable. Let’s
name it Main (change the highlighted text above to
Main). Now, let’s enter the fields that we want to store. The
element should look like this when finished:

Visual Studio will now take this DataSet and make a set of
classes for us that we can use. So now, let’s take a look at the Load and Save
buttons on the main form. These events make use of ConfigPathname,
this is a field that is predefined in the demo. ConfigPathname just
holds the path and filename of the settings file.

When loading the DataSet back, it is necessary to check each
field for null. In our demo, they would never be null, but if you later add
fields and your application tries to load a file that was saved with an older
version, fields could be null. End users might also directly edit your settings
files. Accessing a field while it is null will generate an exception.

If you run the demo, you can enter some test values and then click Save.

After clicking Save, the demo will create a .settings file in the same
directory as the .exe. Normally, this is
bin/debug/SettingsDemo.exe.Settings. If you open this file, you will see
it is a standard XML file and can easily be edited.

Now, if you run the application again, you can click the Load button to load
these settings.

In this demo, we only stored one row in the DataTable. But
DataTables can contain multiple rows, and a DataSet
can even contain multiple related or unrelated DataTables.

Conclusion

XML files are a widespread standard that allows easy storage of structured
typed data. Use of XML files allows easy editing by end users, and even by other
software. Using typed DataSets, you can easily store your settings
in XML files.

License

This article, along with any associated source code and files, is licensed under The BSD License

Comments and Discussions

I have 24 values that I want to save, would like to loop through instead of a separate line of code for each. Anyone accomplish that? I'm working on it but haven't got there yet.
xRow.Forward(i) gives the error that Forward is not a member of .Settings.ForwardRow

Your solution is fine and will work well. You have explained it well enough too, but datasets are not meant for this purpose. Simply using XPath and providing expressions to get values is the right way of doing it for me.

Of course Datasets were not designed for this. They just work very well, and epescially when I wrote this .NET 1.1 was the only version out. Since then there are many more options. There is nothing wrong with raw XML, but its more work for most especially those no familiar with the deeper details of XML.

But even in the world of .NET 3.5 I find myself often using datasets because they are very easy to use.

Chad Z. Hower, a.k.a. Kudzu
"Programming is an art form that fights back"

That is actually a feature most people want. The ability for users to edit.

If you want to hide something, you need to encrypt it. The level of encryption depends on the data. You can also encxrypt just individual keys, instead of the whole file.

There are encryption functions built into .NET, or for passwords and things you can use easier more standard practices of storing hashes. Which hash/encryption again depends on your required security level.

Chad Z. Hower, a.k.a. Kudzu
"Programming is an art form that fights back"

Great article. Thanks to it I'm successfully using XML files for application settings and data. However I realize that I may run into a problem in the future. Because my application is constantly being improved I add new features to it now and then. If I need to store any new data I'll have to revise my dataset by adding fields. If I then try to load an old XML file (from before the fields were added) it will throw an exception due to the fields mismatch.

Is there any elegant way to get around this limitation? I could write some functions to identify the version of the dataset in the XML file and then convert old to new versions but that seems a bit clunky. There must be a better way (at least I'm hoping there is).

This is a great article...I was just wondering what would be the best way to handle multiple data tables writing to the same file...coz it seems that the current method suggested will create a new settings file everytime and hence remove the sections corresponding to other tables..do i need to fill the DS everytime i plan to update a table?

When you click a button, a colordialog appears where the user selects a color. After that, a flat button you cannot click, shows that color. When i click the Save button, the rgb values of that color are written as:

<color>xxx xxx xxx
(xxx xxx xxx = R G B)

in the settings file. So far so good.

But i can't seem to load the color so that it is applied on the button. I tried this:

If Not xRow.IsColorRNull() Then
view32Dialog.Color = xRow.Color
End If

This doesn't work. The words xRow.Color are blue underlined, and i get the message "Error: Value of type 'String' cannot be converted to 'System.Drawing.Color". So im kinda stuck here.

Can you help me?

I also succesfully added a combobox control and this works fine, since this is pretty much like a textbox.