Saving Form Settings


Like many developers at Microsoft, I spend a good chunk of my free time writing tools, or fun little programs that use some new SDK, or even applications requested by friends or family to help them do some task better and/or faster.  Many of these materialize as Windows Forms applications simply because System.Windows.Forms makes it very easy to quickly throw together a quality interface with very little code driving it.  A large majority of these UIs have textboxes that store paths to files or directories, checkboxes that store yes/no preferences, etc, and I end up writing one-off methods to load and store these settings to the registry, or to isolated storage, or to an XML file, or to some other store for maintaining state between executions.  Tonight, I got tired of wasting those two minutes for each app and hacked together a simple class to work with 90% of the WinForms tools I write.


public class SettingsSaver


{


    private static string _settingsKey = @”Software\Toub”;


 


    public static string SettingsKey { get { return _settingsKey; } set { _settingsKey = value; } }


 




    public static void Register(Form f)
    {

        if (f != null)

        {

            f.Load += new EventHandler(LoadSettings);


            f.Closing += new System.ComponentModel.CancelEventHandler(SaveSettings);


        }


    }


 




    private static void LoadSettings(object sender, EventArgs e) 
    {

        Form f = sender as Form;


        if (f == null) return;


        try


        {


            using (RegistryKey parentKey = Registry.CurrentUser.OpenSubKey(_settingsKey, false))


            {


                if (parentKey != null)


                {


                    using (RegistryKey key = parentKey.OpenSubKey(Assembly.GetEntryAssembly().GetName().Name))


                    {


                        if (key != null) LoadSettings(key, f);


                    }


                }


            }


        }


        catch(Exception exc)


        {


            Debug.Write(exc.ToString());


        }


    }



 


    private static void LoadSettings(RegistryKey key, Control parent)


    {


        foreach(Control c in parent.Controls)


        {


            if (c is CheckBox) ((CheckBox)c).Checked = bool.Parse((string)key.GetValue(c.Name, ((CheckBox)c).Checked.ToString()));


            else if (c is TextBox) ((TextBox)c).Text = (string)key.GetValue(c.Name, ((TextBox)c).Text);


            else if (c is RadioButton) ((RadioButton)c).Checked = bool.Parse((string)key.GetValue(c.Name, ((RadioButton)c).Checked.ToString()));


            else if (c is TrackBar) ((TrackBar)c).Value = int.Parse((string)key.GetValue(c.Name, ((TrackBar)c).Value.ToString()));


            else if (c.Controls.Count > 0) LoadSettings(key, c);


        }


    }


 


    private static void SaveSettings(object sender, System.ComponentModel.CancelEventArgs e)


    {


        Form f = sender as Form;


        if (f == null) return;


        try


        {


            using (RegistryKey parentKey = Registry.CurrentUser.CreateSubKey(_settingsKey))


            {


                using (RegistryKey key = parentKey.CreateSubKey(Assembly.GetEntryAssembly().GetName().Name))


                {


                    if (key != null) SaveSettings(key, f);


                }


            }


        }


        catch(Exception exc)


        {


            Debug.Write(exc.ToString());


        }


    }


 




    private static void SaveSettings(RegistryKey key, Control parent)
    {

        foreach(Control c in parent.Controls)


        {


            if (c is CheckBox) key.SetValue(c.Name, ((CheckBox)c).Checked.ToString());


            else if (c is TextBox) key.SetValue(c.Name, ((TextBox)c).Text);


            else if (c is RadioButton) key.SetValue(c.Name, ((RadioButton)c).Checked.ToString());


            else if (c is TrackBar) key.SetValue(c.Name, ((TrackBar)c).Value.ToString());


            else if (c.Controls.Count > 0) SaveSettings(key, c);


        }


    }


}


Now when I write an app, all I need to do is add the following line to my Form’s constructor:
        SettingsSaver.Register(this);
and all of the settings for my form wil be automatically loaded when it’s opened and saved when it’s closed.

Comments (6)

  1. KevinT says:

    Nicely done! Thanks a lot for this, it is going to save me a lot of time 😛

    Incedently, if anyone wants to use this code in a class, they will need to use the following namespaces…

    using System;

    using System.Windows.Forms;

    using System.Reflection;

    using System.Diagnostics;

    using Microsoft.Win32;

    (just in case ppl get stuck)

    Regards

    KevinT

  2. Intel96 says:

    I want to save setting like your suggested in your class, but I want a checkbox on the messagebox to ask the user to save the setting. Something like never asked this question again…

    How do you add this?

  3. There’s no easy way to modify the standard message box… your best bet would be to simply create a new form that has whatever features you want (including a checkbox) and then ShowDialog on it instead of doing MessageBox.Show.

  4. Perry Rapp says:

    Very nice code snippet.

    I did something much like it — thank you for the inspiration.

    * I combined the Load & Save loops into a single loop (LoadSaveSettings), with a direction value, so that new controls only need be added to one location.

    * I modifed the storage code for TextBoxes to encrypt (DPAPI) values in password text boxes (I’m testing on the SystemPasswordChar right now).

    * I used a Settings class, instead of RegKey, so I can abstract storing a string/value pair — my version does that via a Settings class, which talks to a SettingsStorageProvider which it gets from a factory of such — so that the decision whether to store via XML or registry can be made at a much higher level.

    * I return a FormSettings object from the single-line invocation (your Register) call, which can be ignored (for a one-line form solution, like yours), or caught, to adjust settings (eg, use customized entropy values for keys, or to use to save the settings at other points than the close).

    * I adjusted the save code to not save if the DlgResult is set to Cancel, as I don’t like saving settings when user is cancelling a dialog.

Skip to main content