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.

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.

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.

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

internalsealedclass 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.

Comments and Discussions

Edit: I fixed my problem. I set the serialization to XML and had to type in the object type in the Settings 'Type' field. I also added code to allow both objects to be XML serializable.

Hi. I'm having trouble with my custom object saving to the user settings. I followed your code to the T. My object has a property which is a List of another custom object. I cannot get this setting to persist. When the application is loaded, this setting is always null.

This works well for using with Most Recently Used files in the menu strip. If you make an update to the executable or replace it, then your settings are lost. If there was a way to keep the settings, then this would be a great way to hide your settings from the user.

I've tried to save the custom datatype as string or xml format, but it didn't work.Is there a way to save the data as string or xml so the user.config can be modified sometimes when it is necessary.Thanks.

I would never say you could not; however the reason for the article is to address exactly what you are trying to achieve, which is to persist a custom data type. Before you feel that you already know the purpose of my article, please bear with me as I try to answer your question. If you look closely at the code, you will notice that custom objects are stored as binary objects. To modify the custom objects, or delete them entirely, you would do it programmatically. To see that in action (modifications and deletes), please download a free application demo and source at my website titled, “Textbox AutoComplete”. I am not sure if Code Project will allow me to show the URL in my reply. If they delete the URL, please let me know and I will find another way to get the URL to you. Go to www.ciaovista.com, and then near the bottom of the page, look for the Textbox AutoComplete source and demo.

This, my friend, is a great implementation of System.Configuration.ApplicationSettingsBase. For the last several years, I've always used the XmlSerialization features or StreamReader to write settings to .xml or .ini but this way is so elegant and clean. I especially like the SortedList<t> to store control names and their values. Brilliant!

Thanks! There is an even better way to make use of the System.Configuration.ApplicationSettingsBase. I hinted at it in my second article on the same subject. See http://www.codeproject.com/KB/cs/WinAppUserSettings2.aspx

If you would like to see how I actually coded for my own application, please let me know at frankgennaro@gmail.com, and I will send you the code. Just put "CODE PROJECT" in the subject so I don't miss it.