User Settings Applied

Introduction
Although just one among many requirements, the capability of a software to remember user input and reuse that information upon recurring operations is a criterion of quality which directly influences user experience. In the wild, however, practice shows that user settings are insufficiently supported: Why can't that software remember this?
Analyzing the reasons for that, the following items come to mind:
- Integration of a user setting is too tedious
- Existing tools offer limited support to manage user settings
- User settings cannot be integrated dynamically
- Migration of user settings upon program updates is not well defined
This article describes a component that shows how to easily implement user settings. The following goals were driving its development:
- Simple integration of a user setting: optimally, just a single statement per setting
- The component should be capable of supporting Console-, WinForms- and WPF-applications
- Compatibility to the .NET 2.0/3.x configuration must be ensured
- Standard components should support recurring needs, such as, for example, location and size of a window, or grid column layout
- XAML driven user settings
- Tracking settings changes
- Collecting settings dynamically
- Automatic migration of user settings with new program versions
- Automatic generation of multiple, context-dependent, configuration sections
- Bind settings to class properties using attributes (new)
The following sample shows a simple usage of this component:
// ------------------------------------------------------------------------
class MyApplication
{
// ----------------------------------------------------------------------
public MyApplication()
{
settings = new ApplicationSettings( this ); // register class settings
} // MyApplication
// ----------------------------------------------------------------------
[PropertySetting] // register setting using an attribute
public int MyValue { get; set; }
// ----------------------------------------------------------------------
public void Execute()
{
settings.Load(); // load settings considering previous versions
...
settings.Save(); // save settings to custom configuration section
} // Load
// ----------------------------------------------------------------------
// members
private readonly ApplicationSettings settings;
} // class MyApplication
Introduction to the .NET Configuration
Since CLR 2.0, the .NET Framework offers an extensive configuration module in System.Configuration
. It differentiates between program and user settings:
Type | File | Location | Occurrence | Usage/Administration |
Application | app.config | Program Folder | 1 per installation | Visual Studio Project Properties: Settings |
User | user.config | User Profile Folder | 1 per user | Derivation of ApplicationSettingsBase |
The usage scenario determines which type of setting to choose:
Criterion/Requirement | Application Setting | User Setting |
Setting is the same for all users (e.g., database connection) | x | |
Setting can vary per user (e.g., theme) | x | |
Temporary/local setting (e.g., location and size of a window) | x | |
Storage of user input or selection (e.g., text alignment) | x | |
Necessity to store settings fine grained (e.g., per plug-in) | x |
The matrix shows that the usage of user settings is preferable in many scenarios!
Control over the user settings is gained through inheriting from the class ApplicationSettingsBase
. A single setting value can be defined via a property and a property attribute. The methods Reload()
, Reset()
, Save()
, and Upgrade()
determine the runtime behavior. The following illustration shows the data flow of the .NET user configuration:

The 'Default Value' is defined through the property attribute DefaultSettingValueAttribute
. The value 'Init Value' is controlled by the .NET Framework. Access to the value of 'Session Value' occurs through the property which is marked with the UserScopedSettingAttribute
, which in turn uses ApplicationSettingsBase.Item
.
The methods Reload()
and Reset()
support freshly loading all settings and setting them back to their 'Default Values, respectively.
When performing the first Save()
, all user settings get stored in the XML file user.config. With every following program launch, the .NET Framework automatically loads them again (action Start). Where that configuration file will be located is influenced by several factors:
- Profile Directory: The local or roaming profile directory (e.g., C:\Documents and Settings\MyName)
- Company Name: The value of the
AssemblyCompanyAttribute
in AssemblyInfo.cs - App Name: The value of the
AssemblyProductAttribute
in AssemlyInfo.cs - Evidence Type and Evidence Hash: Information derived from the app domain evidence
- Version: The value of the
AssemblyVersionAttribute
in AssemblyInfo.cs
If any of these factors change, the user settings will be stored (and looked for) in a different folder. The method Upgrade()
offers some support for migrating user settings from previous versions. Care should be taken, however, when changing either the company or the application name, as these changes will prevent future upgrades.
The .NET user settings configuration is capable of storing the values of several ApplicationSettingsBase
s in the same file. The SettingsKey
acts as a grouping mechanism to separate them in the XML file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup,
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Itenso.Configuration.WindowSettings.MySettings1"
type="System.Configuration.ClientSettingsSection, System,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<section name="Itenso.Configuration.WindowSettings.MySettings2"
type="System.Configuration.ClientSettingsSection, System,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<Itenso.Configuration.WindowSettings.MySettings1>
<setting name="MySetting1" serializeAs="String">
<value>Value1</value>
</setting>
</Itenso.Configuration.WindowSettings.MySettings1>
<Itenso.Configuration.WindowSettings.MySettings2>
<setting name="MySetting2" serializeAs="String">
<value>Value2</value>
</setting>
</Itenso.Configuration.WindowSettings.MySettings2>
</userSettings>
</configuration>
The Client Settings FAQ offers a lot more interesting insights about the .NET configuration. The article Read/Write App.Config File with .NET 2.0 demonstrates the management of application settings.
Extended .NET User Settings
To achieve the desired improvements, a user setting has been separated from ApplicationSettingsBase
. The new element Setting
binds a setting value to a definable source. The following Setting
classes are available:
Class | Technology | Function |
Setting |
Console, WinForms, WPF | Save/load, and integration to the System.Configuration user settings |
ValueSetting |
Console, WinForms, WPF | Setting value without binding |
FieldSetting |
Console, WinForms, WPF | Binding to a class field |
PropertySetting |
Console, WinForms, WPF | Binding to a class property |
DataGridViewSetting |
WinForms | DataGridView column settings |
DependencyPropertySetting |
WPF | Binding to a dependency property |
ListViewSetting |
WPF | ListView column settings |
The class Setting
acts as the base class of all settings. The class ValueSettingBase
takes the role of simple value based settings.
The following illustration shows how these extended user settings influence the data flow:

Load()
transfers the user settings into a Setting
. Through the integration of the upgrade functionality into Load()
, we have achieved the automatic upgrade of user settings. The actions Reload()
and Reset()
synchronize the 'Setting Value' with the 'Session Value'. Save()
uses the 'Setting Value' as its source. Settings with a binding such as PropertyBinding
will use the class property value.
The property Setting.HasChanged
indicates whether the 'setting value' has changed with respect to the 'Session Value'. This can be used to confirm the saving of settings.
For automating the runtime behavior, various derivations of ApplicationSettingsBase
are available:
Class | Technology | Function |
ApplicationSettings |
Console, WinForms, WPF | Settings management, Save/Load, Auto-Upgrade |
ControlSettings |
WinForms | Load/Save for a Control |
FormSettings |
WinForms | Load/Save for a Form with Location /Size /WindowState |
WindowApplicationSettings |
WPF | Load/Save for an Application |
FrameworkElementSettings |
WPF | Load/Save for a FrameworkElement |
WindowSettings |
WPF | Load/Save for a Window with Location /Size /WindowState |
The class ApplicationSettings
is the base class for all settings.
The SettingCollector
element allows to dynamically merge settings. The following SettingCollector
classes are available:
Class | Technology | Function |
PropertySettingCollector |
WinForms, WPF | Binding to a child class property |
DependencyPropertySettingCollector |
WPF | Binding to a child class dependency property |
A SettingCollector
iterates over the UI element hierarchy, and registers a property setting with all instances of a class. Applying the PropertySettingCollector
, for example, on CheckBox.IsChecked
will store the state of all checkboxes in the user settings. The event SettingCollector.CollectingSetting
allows to control the registering of each setting individually. For performance reasons, a SettingCollector
should not combine more than 10 settings.
Using the Code
Console Application
Support for user settings is achieved through the class ApplicationSettings
:
// ------------------------------------------------------------------------
class Program
{
// ----------------------------------------------------------------------
[PropertySetting( DefaultValue=-1 )]
public int StatusCode { get; set; }
// ----------------------------------------------------------------------
public void Execute()
{
ApplicationSettings applicationSettings = new ApplicationSettings( this );
applicationSettings.Load();
Console.Write( "Please enter a number: " );
statusCode = int.Parse( Console.ReadLine() ); // modifying the field value
applicationSettings.Save();
} // Execute
// ----------------------------------------------------------------------
static void Main()
{
new Program().Execute();
} // Main
} // class Program
Entering the value 22 leads to the following user configuration:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings">
<section name="Itenso.Configuration.ApplicationSettings.Program"
type="System.Configuration.ClientSettingsSection, System,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<Itenso.Configuration.ApplicationSettings.Program>
<setting name="StatusCode" serializeAs="String">
<value>22</value>
</setting>
<setting name="UpgradeSettings" serializeAs="String">
<value>False</value>
</setting>
</Itenso.Configuration.ApplicationSettings.Program>
</userSettings>
</configuration>
The meaning of the value UpgradeSettings
will be shown later on.
WinForms Application
The following example shows how to implement custom application or form settings:

Control Settings
Handling the user settings of Control
and its derivations is supported by the class ControlSettings
:
// ------------------------------------------------------------------------
public class MyListBox : ListBox
{
// ----------------------------------------------------------------------
public MyListBox()
{
if ( DesignMode )
{
return;
}
ControlSettings controlSettings = new ControlSettings( this );
controlSettings.Settings.Add(
new PropertySetting( // bind setting to the property
this, // source component
"SelectedIndex" ) ); // property name
} // MyListBox
} // class MyListBox
Form Settings
User settings of a Windows Form
and its derivations are controlled by the class FormSettings
:
// ------------------------------------------------------------------------
public partial class MyForm : Form
{
// ----------------------------------------------------------------------
public MyForm()
{
InitializeComponent();
FormSettings formSettings = new FormSettings( this );
} // MyForm
} // class MyForm
FormSettings
automatically stores the location, size, and the state of a window. Several switches such as FormSettings.UseLocation
allow you to customize the automatic behavior. Of special interest is the switch FormSettings.AllowMinimized
(default=false
) which controls the storage behavior for Windows in the minimized state.
DataGridView Settings
Position (order) and width of DataGridView
columns can be stored in the user settings using the class DataGridViewSetting
:
// ------------------------------------------------------------------------
public partial class MyForm : Form
{
// ----------------------------------------------------------------------
public MyForm()
{
InitializeComponent();
FormSettings formSettings = new FormSettings( this );
formSettings.Settings.Add( new DataGridViewSetting( myDataGridView ) );
} // MyForm
} // class MyForm
The example DataGridView
also contains a demonstration of a save confirmation.
Collected Settings
The following example shows how to store all the CheckBox
state values of a Form
:
// ------------------------------------------------------------------------
public partial class MyForm : Form
{
// ----------------------------------------------------------------------
public MyForm()
{
InitializeComponent();
FormSettings formSettings = new FormSettings( this );
formSettings.CollectingSetting +=
new SettingCollectorCancelEventHandler( FormSettingsCollectingSetting );
formSettings.SettingCollectors.Add( new PropertySettingCollector
( this, typeof( CheckBox ), "Checked" ) );
} // MyForm
// ----------------------------------------------------------------------
private void FormSettingsCollectingSetting
( object sender, SettingCollectorCancelEventArgs e )
{
if ( e.Element == this.myCheckBox ) // exclude this checkbox
{
e.Cancel = true;
}
} // FormSettingsCollectingSetting
} // class MyForm
WPF - Code Behind
The accompanying example shows how to implement custom application or window settings:

DerivedSettingsWindow.xaml uses BaseWindow
to demonstrate how a Window
inheritance hierarchy can be built. By including the WindowSettings
in the base class BaseWindow
, all the derivations and XAML instances will automatically store the location, size, and state.
FrameworkElement Settings
Handling user settings of FrameworkElement
and its derivations is supported by the class FrameworkElementSettings
:
// ------------------------------------------------------------------------
public class MyListBox : ListBox
{
// ----------------------------------------------------------------------
public MyListBox()
{
if ( DesignerProperties.GetIsInDesignMode( this ) )
{
return;
}
FrameworkElementSettings listBoxSettings = new FrameworkElementSettings( this );
listBoxSettings.Settings.Add(
new DependencyPropertySetting( // bind setting to the dependency-property
this, // source component
SelectedIndexProperty ) ); // dependency-property name
} // MyListBox
} // class MyListBox
In contrast to the WinForm variant, WPF offers an elegant way to bind a Setting
to a property with the DependencyProperty
. Invalid bindings will be recognized at compile time.
Window Settings
The settings of a Window
and its derivations is controlled by the class WindowSettings
:
// ------------------------------------------------------------------------
public partial class MyWindow : Window
{
// ----------------------------------------------------------------------
public MyWindow()
{
WindowSettings windowSettings = new WindowSettings( this );
} // MyWindow
} // class MyWindow
WindowSettings
automatically stores location, size, and state of a window. The switches FormSettings.UseLocation
, FormSettings.AllowMinimized
, and so on control the saving behavior (see above).
ListView Settings
Position (order) and width of ListView
columns can be stored in the user settings using the class ListViewSetting
:
// ------------------------------------------------------------------------
public partial class MyWindow : Window
{
// ----------------------------------------------------------------------
public MyWindow()
{
WindowSettings windowSettings = new WindowSettings( this );
windowSettings.Settings.Add( new ListViewSetting( myListView ) );
} // MyWindow
} // class MyWindow
The example ListView
also contains a demonstration of a save confirmation. The article ListView Layout Manager demonstrates how to restrict column widths of ListView
s and how to support proportional column widths.
Collected Settings
The following example shows how to store all the CheckBox
state values of a Window
:
// ------------------------------------------------------------------------
public partial class MyWindow : Window
{
// ----------------------------------------------------------------------
public MyWindow()
{
WindowSettings windowSettings = new WindowSettings( this );
windowSettings.CollectingSetting +=
new SettingCollectorCancelEventHandler( WindowSettingsCollectingSetting );
windowSettings.SettingCollectors.Add( new DependencyPropertySettingCollector
( this, CheckBox.IsCheckedProperty ) );
} // MyWindow
// ----------------------------------------------------------------------
private void WindowSettingsCollectingSetting
( object sender, SettingCollectorCancelEventArgs e )
{
if ( e.Element == this.myCheckBox ) // exclude this checkbox
{
e.Cancel = true;
}
} // WindowSettingsCollectingSetting
} // class MyWindow
WPF - XAML
User settings can be declared in XAML as follows:
<Window
x:Class="Itenso.Solutions.Community.ConfigurationWindowsDemo.XamlUserSettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:config="clr-namespace:Itenso.Configuration;
assembly=Itenso.Configuration.Windows"
config:WindowSettings.Settings="XamlWindowSettings">
<StackPanel>
<CheckBox
x:Name="MyOption"
Content="My Option"
config:DependencyPropertySetting.Property=
"{x:Static CheckBox.IsCheckedProperty}" />
</StackPanel>
</Window>
The attribute config:WindowSettings.Settings
assigns the WindowSetting
to the window. Storage of the Window
's location/size/state happens automatically. Upon upgrading, the values of the previous version will be migrated automatically, too.
The attribute config:DependencyPropertySetting.Property
leads to the treating of CheckBox.IsChecked
as a user setting and hence its storage.
Important: For the property value to be stored, the element has to have a value in its x:Name
.
The example above leads to the following configuration data:
<Itenso.Configuration.WindowSettings.XamlWindowSettings>
<setting name="Window.Top" serializeAs="String">
<value>203</value>
</setting>
<setting name="Window.Height" serializeAs="String">
<value>200</value>
</setting>
<setting name="Window.Left" serializeAs="String">
<value>813</value>
</setting>
<setting name="Window.Width" serializeAs="String">
<value>713</value>
</setting>
<setting name="Window.WindowState" serializeAs="String">
<value>Normal</value>
</setting>
<setting name="UpgradeSettings" serializeAs="String">
<value>False</value>
</setting>
<setting name="MyOption.IsChecked" serializeAs="String">
<value>True</value>
</setting>
</Itenso.Configuration.WindowSettings.XamlWindowSettings>
ListView Settings
Using XAML, the position (order) and width of ListView
columns can be stored in the user settings as follows:
<Window
x:Class="Itenso.Solutions.Community.ConfigurationWindowsDemo.XamlUserSettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:config="clr-namespace:Itenso.Configuration;
assembly=Itenso.Configuration.Windows"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
config:WindowSettings.Settings="XamlWindowSettings">
<StackPanel>
<ListView
Name="MyListView"
ItemsSource="{Binding MyList}"
config:ListViewSetting.Settings="MyListView">
...
</ListView>
</StackPanel>
</Window>
The attribute config:ListViewSetting.Settings
defines the name of the setting. The assignment of config:WindowSettings.Settings
to the Window
is necessary.
Collected Settings
The following example shows the usage of a SettingCollector
in XAML:
<Window
x:Class="Itenso.Solutions.Community.ConfigurationWindowsDemo.XamlUserSettingsWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:config="clr-namespace:Itenso.Configuration;
assembly=Itenso.Configuration.Windows"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
config:WindowSettings.Settings="XamlWindowSettings"
config:WindowSettings.CollectedSetting="{x:Static CheckBox.IsCheckedProperty}">
<StackPanel>
<CheckBox
x:Name="MyOption"
Content="My Option"
config:WindowSettings.ExcludeElement="True" />
</StackPanel>
</Window>
The config:WindowSettings.CollectedSetting
registers a DependencyPropertySetting
. This only considers elements which contain a defined x:Name
. Using config:WindowSettings.ExcludeElement
allows to exclude an element from registration.
Points of Interest
- The sample applications demonstrate how to implement a 'Save as Default' feature per Form/Window
- Specifying an invalid name for a
FieldSetting
or aPropertySetting
will result in an exception readonly
fields for aFieldSetting
will lead to an exceptionPropertySetting
: an assigned property withoutget; set;
accessors will lead to an exception- The setting
UpgradeSettings
has a default value oftrue
and will be set tofalse
after an upgrade - A
Setting
provides runtime control via the eventsValueSaving
andValueLoading
ApplicationSettings.UseAutoUpgrade
controls the auto-upgrade behaviour- The
ApplicationSettings
uses aLocalFileSettingsProvider
- The
Setting
serialization format can be specified with the propertyValueSettingBase.SerializeAs
. Examples of how to serialize settings in a binary format can be found inDataGridViewSetting
andListViewSetting
- The store behavior can be influenced with the
FormSettings.SaveCondition
andWindowSettings.SaveCondition
properties, so it honors theDialogResult
- The method
Setting.CreateSettingProperty()
demonstrates how to dynamically include aSettingsProperty
WindowSettings.OnWindowSettingsChanged
andDependencyPropertySetting.FindApplicationSettings
demonstrate how a property (DependencyPropertySetting.ApplicationSettingsProperty
) can dynamically be assigned to an object and evaluated. The very case uses the property to determine whichApplicationSettings
should be assigned aDependencyPropertySetting
- The
DepedencyPropertySetting
will be assigned to the firstApplicationSettings
which is found in the parent hierarchy. This can then either be aWindowSettings
or aFrameworkElementSettings
History
- 15th February, 2011
- Enhanced support for maximized window in multi-monitor environment - thanks Ryan
- Added projects and solutions for Visual Studio 2010
- Refactored code - or rather 'ReSharped'
- 18th March, 2009
ApplicationSettings
: Added new eventsSettingSaving
andSettingLoading
SettingValueEventArgs
andSettingValueCancelEventArgs
: New propertyTargetValue
which allows to change the setting value within the save/load eventsFormSettings
andWindowSettings
: Made all settings public available
- 15th January, 2009
- Added
FieldSettingAttribute
andPropertySettingAttribute
- Refactored component to use automatic properties
- Added sample with attribute settings
- Added
- 20th May, 2008
- Collecting settings: new classes
PropertySettingCollector
andDependencyPropertySettingCollector
- Tracking setting changes: new properties
Setting.HasChanged
andSettingCollection.HasChanges
- WinForms: save settings depending on
Form.DialogResult
, new propertyFormSettings.SaveCondition
- WPF: save settings depending on
Window.DialogResult
, new propertyWindowSettings.SaveCondition
- Error handling: new properties
Setting.ThrowOnErrorSaving
andSetting.ThrowOnErrorLoading
- Collecting settings: new classes
- 10th May, 2008
- WinForms: new setting
DataGridViewSetting
- WPF: new setting
ListViewSetting
- WinForms sample application: new samples for color and font settings
- WPF sample application: new sample for a color setting based on a custom dependency property
- Added link to article Read/Write App.Config File with .NET 2.0
- Added link to article ListView Layout Manager
- WinForms: new setting
- 3rd May, 2008
- Initial public release
Post Comment
It ingesting a salt good timing. the first afraid so way. The for is health threat is. Chances 20 you threat who old.