Click here to Skip to main content
Click here to Skip to main content

Windows Forms - Creating and Persisting Custom User Settings in C#

, 6 Sep 2008
Rate this:
Please Sign up or sign in to vote.
This article discusses the creation and persistence of .NET Framework and custom objects within the Windows User Settings.

Introduction

If you have configured property settings, you no doubt noticed the “Browse” choice as illustrated in Figure 1 to configure a limited set of objects, and I do mean “limited”. After much pain due to countless hours of webpage browsing that, in most cases, leads to dead ends, one can eventually figure out how to correctly use the “Browse” choice to persist the various objects that are provided in the “Browse” choice list.

While the bad news is that we are not going to discuss how to use the “Browse” choice list, the good news is that we will discuss how to persist custom objects (instances of classes you create) and just about any object the Framework provides. What this means is that the painful experience of trying to use the “Browse” choice to persist objects never has to be used until Microsoft does a better job of making it developer friendly.

OK, so maybe, you don’t agree, and find the “Browse” choice easy to use. If that is the case, you may still find this article interesting. Among other things, we will persist a “System.Collections.Generic.SortedList” object which is not found in the “Browse” choice list. Additionally, we will persist a custom (user defined) object.

CustomUserSettingsDemo

Using the Code

The first code snippet we will discuss is a class shown below. The class is used to persist a Generic SortedList. The GenericSortedListDemo class, like any class object we want to persist, must inherit ApplicationSettingsBase.

The next important thing to notice are the attributes on the top of the NamesGenericSortedList property.

The UserScopedSetting attribute, as opposed to the ApplicationScopedSetting attribute, is very important. It is that attribute that will allow you to persist the object. If you did use the ApplicationScopedSetting attribute, what would happen is that when you call the Save method (as seen in the code you can download) to persist the object, the Save method will lead you to believe the object was written to disk when, in fact, it was not!

The SettingsSerializeAs attribute must specify Binary as our code does.

The last attribute, DefaultSettingValue, has the effect of creating an object with no members, meaning the count is zero for the Generic SortedList object that is created.

Our job then is to create an instance of GenericSortedListDemo, fill it with data, then persist it to disk. You can see how that is done by viewing the code you download. Exactly where it is stored will not be discussed here.

internal sealed class GenericSortedListDemo : ApplicationSettingsBase
{
    // If you used [ApplicationScopedSetting()] instead of [UserScopedSetting()],
    // you would NOT be able to persist any data changes!
    [UserScopedSetting()]
    [SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Binary)]
    [DefaultSettingValue("")]
    public System.Collections.Generic.SortedList<int, /> NamesGenericSortedList
    {
        get
        {
            return ((System.Collections.Generic.SortedList<int, />)
                     this[&quot;NamesGenericSortedList&quot;]);
        }
        set
        {
            this[&quot;NamesGenericSortedList&quot;] = 
                 (System.Collections.Generic.SortedList<int, />)value;
        }
    }
}

The next object that we will discuss is a custom (user defined) object. You will find that creating an instance of a custom object, filling it, and then persisting it to disk is very similar to what we just did with a System.Collections.Generic.SortedList object.

Our custom class is called EmployeeList. In that class shown below, you will see a required attribute: [Serializable]. Without it, you will not be able to persist an instance of the class. The class contains an ArrayList which consists of System.Collections.DictionaryEntry objects, where each DictionaryEntry object contains an employee ID and employee name.

[Serializable]
internal class EmployeeList
{
    private ArrayList _employees = null;

    public EmployeeList()
    {
        _employees = new ArrayList();
    }

    public System.Collections.IEnumerator Employees
    {
        get
        {
            return _employees.GetEnumerator();
        }
    }

    public void AddEmployee(int id, string name)
    {
        _employees.Add(new DictionaryEntry(id, name));
    }

    public void RemoveEmployee(int id, string name)
    {
        DictionaryEntry de = new DictionaryEntry(id, name);
        if (_employees.Contains(de))
        {
            _employees.Remove(de);
        }
    }

    public void ClearAllEmployees()
    {
        _employees.Clear();
    }

    public int EmployeesCount
    {
        get
        {
            return _employees.Count;
        }
    }
}

Below is the code that utilizes an instance of EmployeeList. It is very similar to what we did earlier.

internal sealed class CustomEmployeesDemo : ApplicationSettingsBase
{
    // If you used [ApplicationScopedSetting()] instead of [UserScopedSetting()],
    // you would NOT be able to persist any data changes!
    [UserScopedSetting()]
    [SettingsSerializeAs(System.Configuration.SettingsSerializeAs.Binary)]
    [DefaultSettingValue(&quot;&quot;)]
    public EmployeeList CustomEmployees
    {
        get
        {
            return ((EmployeeList)this[&quot;CustomEmployees&quot;]);
        }
        set
        {
            this[&quot;CustomEmployees&quot;] = (EmployeeList)value;
        }
    }
}

Before you get overly critical of our custom class design, please keep in mind that it is merely an example of how to create and persist custom objects. In a real world scenario, a custom class would certainly not be designed like the demo custom class.

License

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

Share

About the Author

Frank Gennaro 2487219

United States United States
No Biography provided

Comments and Discussions

 
QuestionFIXED - List of my objects [modified] PinmemberMember 85283469-May-12 10:58 
GeneralMy vote of 5 Pinmembermanoj kumar choubey19-Feb-12 21:50 
GeneralNice article but not valuable when updates are made Pinmemberated878-Nov-09 22:21 
GeneralRe: Nice article but not valuable when updates are made PinmemberFrank Gennaro 248721910-Nov-09 9:21 
QuestionCan the custom datatype be saved as String/Xml to user.config Pinmemberfeg200017-Apr-09 8:12 
AnswerRe: Can the custom datatype be saved as String/Xml to user.config [modified] PinmemberFrank Gennaro 248721919-Apr-09 3:14 
GeneralFantastic Pinmemberthund3rstruck5-Oct-08 5:14 
GeneralRe: Fantastic PinmemberFrank Gennaro 248721910-Oct-08 10:14 
GeneralNice Pinmembersam.hill7-Sep-08 5:57 
GeneralRe: Nice [modified] PinmemberFrank Gennaro 24872198-Sep-08 2:03 

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.140826.1 | Last Updated 6 Sep 2008
Article Copyright 2008 by Frank Gennaro 2487219
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid