Introduction

Application settings are a way to persist settings. They are a convenient replacement for INI files or using the Registry. There are a couple of problems, however. It is not easy to persist your own types or collections (generic or otherwise). This article will explore why, and offer a few solutions.

Application settings have two possible scopes, Application and User. I will focus exclusively on user scoped settings here. Application scoped settings are much the same, except they cannot be altered by the user at runtime.

A quick overview

If you create a new WinForms app (I've called mine VersatileApplicationSettings), go to Solution Explorer, and in the Properties folder, you will see a file Settings.settings (referred to as the settings UI from now on) and a 'sub file' called Settings.Designer.cs (referred to as the designer file from now on). The designer file is where the actual code goes. Double clicking the settings UI gives you a pretty UI to create and edit your settings. Every time you make a change through the settings UI, the entire designer file gets rewritten (just the same as a Form's designer file). This is the root of the major problem. Any customization we do has a tendency to be removed every time we use the settings UI - more later!

Normal use

Before we make any changes, let's have a quick look at the designer file's contents. You'll notice that everything is fully qualified right from the global namespace. I've added a using here in the interests of legibility, and ignored the compiler attributes.

First notice that the class derives from the abstract class ApplicationSettingBase. This class gives us the functionality needed to save and synchronize our settings; in other words, the hard work is already done for us! There is also the public static Default property that is the Settings instance we actually work with - almost a Singleton.

Double click the settings UI file and create a new setting StringSetting, leaving the type as string, and save. Now, check the designer file and you'll see a new property (again edited for legibility and to show the important parts).

Pretty straightforward, and it should be clear how we could add our own settings without needing the settings UI. Now that we have this setting, it can be accessed from anywhere in our application, changed, saved, reloaded etc.

Your own types

When selecting types through the UI, there is no way to select our own classes as the type. We can, of course, add our own properties to the designer file, but with two problems: they won't be visible in the settings UI, and they will get overwritten. Ignoring the first problem (who needs the UI anyway!), there are three methods that I know of of working around this. In my least preferred order:

Edit the source of the Settings.settings file (this will allow you to continue to use the settings UI).

Create a new partial file for the Settings class.

Create a new class that derives from ApplicationSettingBase.

Settings.settings

Open the Settings.settings file with any text editor, and you will see it's actually just an XML file that looks something like this:

Once saved, this will work fine. It'll even show in the settings UI, although you won't be able to set a default value (this may be possible using a TypeConverter - I haven't tried). The biggest problem with this approach is you can't use generic lists, so if you wanted, say, a List<MyClass>, it isn't possible (as far as I know).

Settings.cs partial

The second option is to forget about the settings UI altogether. If we add a new class file Settings.cs, change the namespace, and mark it as partial (note the original designer file is partial), we can just add our own properties to the code.

ExtendedSettings class

Although the solution above performs exactly how we want, I prefer the idea of separating out into a separate settings class, so when our custom settings don't appear in the settings UI, it's not a surprise. This is easy enough to do, we just need to follow the basic pattern that the auto generated code produces, i.e., static instance, and add our properties. To make sure that the static instance used is *always* the same instance, I prefer to use a stronger Singleton pattern than Microsoft's. The pattern is taken from here, and the class file is ExtendedSettings.cs.

This works exactly like the previous example, except the settings would be accessed through Properties.ExtendedSettings.Settings instead of Properties.Settings.Default.

The demo

In the attached demo, I've used the last approach to remember the Location and Size of the forms. There are only two forms, but because the settings are stored in a generic list, it can grow as necessary to accommodate as many as you need - all in one setting.

About the Author

Comments and Discussions

Thanks for the informative article - I've been perusing the web looking for help on how to create a partial class of my own for settings instead of using the settings designer that I don't care for. This article helped me get my head around the approach and get me going. I have to admit as a newbie to .NET the Configuration Manager seemed a bit confusing at first. I believe that previous post had a point in that you need to make your object serializable in order to save properly.
Thanks again.

For some reason I missed the notification for the previous post Yeah, non-serializable objects can't be serialized, I never thought to mention that. I will give the article and code a quick look over for other improvements and add that to the edit soon.

I normally use settings file for trivial values. I mark my custom types which needs to persisted as serializable and serialize it using BinaryFormatter and will be persisted on a normal file. This allows to deserialize the whole object graph easily.