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.
Hey! What gives? My class isn’t here! No matter how I browse, I just can’t find it!
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:
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.
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.]
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:
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.