VB.Net’s My.Settings and custom objects/classes; Part Two: Getting My.Settings to recognize your custom object

Read Part one

OK, so far everything has been pretty simple: adhere to the guidelines for making your class Serializable, and deal with complexities by Implementing ISerializable.

So, your next step is to add a Setting, of the type of your custom class, to your application: Right-click your Project name at the top of Solution Explorer, then select Properties from the pop-up menu. This opens the Properties editor; click “Settings” on the left side. Left-click in the first empty box in the Name column, enter a name for your new setting, then click the combobox for Type.

notThere

Hey! What gives? My class isn’t here! No matter how I browse, I just can’t find it!

browse

Now, of course, you should be able to find your Project here, then your custom class, and select it. Unfortunately, at least as of VS 2008, you can’t. Is this a bug? You decide. There is, however, a workaround…or I wouldn’t have bothered writing this article!

Entering your class in the Settings editor

This is where things got interesting for me. I came across many blog articles and forum posts discussing the best approach. Some that I found, of varying usefulness, included:

This article suggested manually editing the “hidden” Settings.Designer.vb file [::shudder:: – what happens if VS regenerates the file?]:

There is a lot of confusion out there about this!

It’s really pretty simple: type it in to the Browse box.

  

Yep. As noted above, add your new setting, name it—in this case we’ll call it “CustomObjectSetting”—click the Type combobox, then click Browse; then type in the full name of your object, including the Root Namespace of the assembly, which, in VB.Net, will be the same as your Project name, unless you specifically changed it. If you’re unsure, click the Application tab at the top of the left side of the Properties editor, and check the “Root namespace” box.

So, if your custom class is named SettingsClass.vb, and your project name or namespace is MyWinFormsProject, you would type the following into the Browse box:

MyWinFormsProject.SettingsClass

typeIn

and that’s it. Really! I promise!

So simple, after so much grief and hand-wringing. Wow.

So now what? How do I use it?

OK, now it’s time for a little databinding, then a little code. It’s really very simple to use the My.Settings object.

I’m going to assume a situation like mine, where you want to bind a settings object to an options dialog window. Go to the Data Sources tab, which should be in the same window as the Solution Explorer, and click on “Add New Data Source…”. Choose “Object” in the next window, click Next, then click the plus sign (+) to expand your project. Select the class that contains your object, then click “Next”, followed by “Finish”.

You will see a representation of your object, with control types next to each property. You can choose which control type to use for each property; generally, you’ll want a textbox for a String property, etc.

setControlTypes

Unless you are using a grid control or something similar that will contain all the properties in one control, you will want to change the top-most item, representing your entire class, from “None” (the well-known circle with a slash icon) to “Details”. Then, when you have everything the way you want, simply drag that top-most item and drop it right on your form; the controls you chose will then be added to the form, all ready to be data-bound, and a BindingSource control will appear at the bottom of your dialog form, generally named after your object: SettingsClassBindingSource. [This is, of necessity due to space constraints, a bit simplified, as it doesn’t deal with binding comboboxes and listboxes, among others, but the gist is here.]

controls

The advantage of dragging the top-most item, rather than dragging each item onto the form separately, is that the controls will generally end up lined up nicely on the form; this can save you hours of position-tweaking of controls! Believe me, I’ve been there…and kicked myself once I realized the better way!

Now, for the code:

Somewhere in the Form_Load() event of the dialog form, add these lines:

If My.Settings.CustomObjectSetting IsNot Nothing Then
      Me.SettingsClassBindingSource.DataSource = My.Settings.CustomObjectSetting
End If

 

Then, in the Event  Handler for your “Save Settings” button, you’ll want to save the settings the user has chosen:

My.Settings.Save()

 

Yup. It’s really that simple.

Of course, if you do things that way, the user has no way to back out of his changes; as soon as a control’s value is changed, that value is in My.Settings; and when the save button is clicked, or (depending on the setting in the Application tab of the project properties) the app is closed, those settings are saved to disk. And there is no clean, easy way to validate the data.

What I usually do is this: first, for each control that is databound, go into its Databinding properties, into “Advanced”, and change the “Data Source Update Mode” to “OnValidation”. Then, I create a form-level variable of the type of my custom settings class; in the Form_Load() event, I check to make sure My.Settings.CustomObjectSetting is not nothing, then set the form-level variable to My.Settings.CustomObjectSetting. I then bind the datasource to the form-level variable, instead of directly to My.Settings.CustomObjectSetting; and, in the “save” button’s Event Handler, I set My.Settings.CustomObjectSetting  to the form-level variable, then call My.Settings.Save().

The big advantage here is that you can add a “cancel” button and have its Event Handler set the form-level variable back to My.Settings.CustomObjectSetting, which will revert the changes the user made as long as they haven’t clicked the “save” button. Also, you can now add code to the _Validating() Event Handler for each control to cleanly validate that control’s data; you can even add an ErrorProvider control to work with your validation code.

Conclusion: Making it simple

It’s really amazing how a simple bug, or oversight—leaving out the ability to browse within your current project for a Setting type—combined with a lack of coherent, centralized documentation, led to so much misinformation and conflicting advice for an issue that is so simple to solve.

If you didn’t know for certain what the iron-clad requirements for a custom class to be used with My.Settings were, that only added to the confusion; you were never certain where the problem lay. Was it a problem with your class—did you have to implement ISerializable?—or was it an issue with how you tried to add your object to the My.Settings editor?

I hope I have clarified the situation, and possibly even added a bit of helpful real-life information as to how to use a custom object with My.Settings.


Advertisements
  1. #1 by Stephen H on December 6, 2016 - 11:35 am

    Thanks very much for this, it helped me to solve my issue. My project had a space in it – if so replace the space with an underscore when doing the Browse (e.g. Project Name.ObjectList becomes Project_Name.ObjectList).

    Here’s my VB code should anyone need a quick reference…

    Public Class DBDetailsCollection
    Public Sub New()
    End Sub

    Private _Details As List(Of DBDetails)

    Public Property Details As List(Of DBDetails)
    Get
    If (_Details Is Nothing) Then
    _Details = New List(Of DBDetails)()
    End If

    Return _Details
    End Get
    Set
    _Details = Value
    End Set
    End Property

    End Class

  2. #2 by Jeff on September 6, 2016 - 10:52 pm

    you have to rebuild the project at some point for the reference to work.. thanks for the details.

  3. #3 by vs00saini on November 5, 2014 - 12:44 am

    To any body else reading this article – Read it carefully word-by-word. Or else you will fail like me.

    To author (Andrew Cushen) – Deep thanks for such precisely written article.

    For C# developers (who are in hurry) :- For testing (or tasting) it –

    Declare something as –

    namespace World
    {
    [Serializable]
    public class Country
    {
    public Country()
    {

    }
    }

    [Serializable]
    public enum Alphabets
    {
    A, B
    }
    }

    Important Point – Build your project else it will not work.

    Open Settings.settings file in Visual Studio (I tested in v 2012) –

    1. Declare new setting and then Browse for Type
    2. Type either World.Country or World.Alphabets
    3. It work perfectly and will be available in list for other classes too (unless the Settings.settings class is regenerated).

    ——————————————
    Again – Thanks goes to Andrew!
    ——————————————

  4. #4 by Keith L on July 21, 2012 - 1:55 am

    Thanks, this worked like a charm!

  5. #5 by Aaron on January 13, 2012 - 1:06 pm

    This is great! Thanks for a clean and well written explaination! You even went into detail about how to easily bind and validate!! Couldn’t thank you enough!!! Keep up the good work, and good luck with the consulting business. The world truly benefits from people like you!!!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: