Binding Properties to Settings
Binding properties to settings is a simple, two-step process from the current code.
Step One: Create the Bindings
Returning to the visual designer, select the TextBox next to the Preferred Path label, then select Data >> PropertyBinding in the Properties pane, and finally click on the ellipsis.
Figure 9 shows the three-step sequence.
 | |
Figure 9. Binding Controls to Settings: To bind a control to a setting, select the control, and then click the ellipsis next to the (PropertyBinding) item under the ApplicationSettings item in the Properties pane. |
|
 | |
Figure 10: Binding Application Settings: This dialog lets you bind form controls to application settings. |
|
|
Clicking the ellipsis opens a dialog for binding properties to application settings as shown in
Figure 10.
 | |
Figure 11: Design-time Binding Results: After binding the Text property to the PreferredPath setting, the correct value appears in the Preferred Path TextBoxeven at design-time. |
Open the drop-down arrow next to the
Text property and select the
PreferredPath setting as shown in
Figure 10, and then close the dialog. You should see two changes, as shown in
Figure 11.
- The text in the TextBox will change from "TBD" (which was entered manually when creating the form) to the PreferredPath application setting value.
- The Text property binding appears in the Properties pane.
Do the same thing for the Domain field, binding it to the
PlanetarySystem setting. But unfortunately, that's as much as you can accomplish in the visual designer. As
Figure 12 shows, only those two settings are available in the binding drop-down.
What happened to the other two settings? The answer is that they're not available because they're not simple stringsand a form can display only strings when it comes right down to it. That is why, if you look back at the code, that we had to convert the setting to a string:
lastRunTimeLabel.Text =
Properties.Settings.Default.LastRunTime.ToString();
 | |
Figure 12. Available Settings: Only two of the four possible settings are available for binding at design-time. |
Automatic design-time binding, then, is not available for all settings, but because so many properties are just strings, design-time binding works fine most of the time.
Step Two: Remove Unneeded Code
Because two of the settings are now automatically bound, you can remove the code that manually bound those settings before. The following code has commented-out references to the
PreferredPath and
PlanetarySystem (two lines in the
Form1_Load method and one line in
SaveToFile):
private void Form1_Load(object sender, EventArgs e)
{
LoadDataGridView(myDataGridView);
// preferredPathTextBox.Text =
Properties.Settings.Default.PreferredPath;
lastRunTimeLabel.Text =
Properties.Settings.Default.LastRunTime.ToString();
// domainLabel.Text =
Properties.Settings.Default.PlanetarySystem;
}
private void SaveToFile()
{
Properties.Settings.Default.ItemList = DGVtoList();
// Properties.Settings.Default.PreferredPath = preferredPathTextBox.Text;
Properties.Settings.Default.LastRunTime = DateTime.Now;
Properties.Settings.Default.Save();
}
As you can see, if this application had
only string settings, you could eliminate
all settings-related code in the
Form1_Load method and you would need only one line of code in
Form1_Closing (or in this case the
SaveToFile method):
Properties.Settings.Default.Save();
Author's Note: If one line of code is still too much, then I'm afraid you will have to switch to Visual Basic for the final leap to zero lines of code, as C# doesn't support this. Yes, with Visual Basic, you do not even need the Save method call (see point #7 in How to: Create Application Settings Using the Designer). But in C#, the typical course of action is to use the Designer to create and bind String settings, and add just the one line of code in your form's FormClosing event handler. |
Creating and Binding a Setting in One Step
The theme for this article is reducing the effort needed to create persistent settings. And you can reduce the effort even further by both creating and binding a setting in a single step. So this time, select the TextBox from the visual designer, and then select the drop-down of the
Text property under the Application Settings item in the Properties pane (see
Figure 13). Ignore the fact that we have already set the
Text property to PreferredPath.
 | |
Figure 13. One-step Setting Creation and Binding: Open the dropdown on the Text property of Application Settings. |
|
 | |
Figure 14. New Application Setting Dialog: This dialog appears when you click the "New..." link from the ApplicationSettings dropdown list. |
|
|
This time, notice the "New
" link near the bottom of the dropdown; when you click that you'll see a New Application Setting dialog (see
Figure 14).
The fields should be familiarname, scope, and valuebut here the type field is absent because the value must be a string. If you did not already have the
PreferredPath setting defined, you could both create it here and bind it hereall in one dialog. See
How to: Add or Remove Application Settings for a nutshell summary on the steps discussed so far.
Additional Binding to Consider
Unfortunately, that easy settings procedure doesn't include everything you might want. For example, one notable component that (oddly) cannot handle automatic settings is a ToolStrip. But fear not! Quoting from Microsoft's
Application Settings Overview documentation:
"Custom controls can also save their own settings by ... the SaveSettings method. The Windows Forms ToolStrip control implements this interface to save the position of toolbars and toolbar items between application sessions."
Therefore, if you want to persist toolbar settings for your application, you only need add these bits of code to the
FormClosing and
Load event handlers:
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
ToolStripManager.SaveSettings(this);
Properties.Settings.Default.Save();
. . .
}
private void MainForm_Load(object sender, EventArgs e)
{
ToolStripManager.LoadSettings(this);
...
}
Note that waiting until your program terminates introduces a slight chance that the tool strip settings might not be saved if your program crashes, for example, but the alternative is putting in separate hooks for each event that is fired from a tool strip change. Too much work and too messy, in my view.
This
discussion thread is another useful source of information on form size and location saving, as is this article:
Saving out a Form's Size and Location using the Application Settings feature
Caveats on Bindings and Settings
The functionality and implementation discussed above fit the ubiquitous 80/20 rule; that is, these techniques will be usefulindeed, valuable80 percent of the time. To be complete, though, it is important to be aware of limitations of bindings and limitations of settings. Since this falls in the 20 percent bucket, I will just state the issues to be aware of, as reported in MSDN; exploring the depths of these issues is beyond the scope of this article.
First, for bindings, components that you are binding to must have the "right stuff", otherwise they will not quite do what is expected. The MSDN article
Application Settings Architecture in the section called "Settings Bindings" describes it this way:
"You can only bind an application setting to a component that supports the IBindableComponent interface. Also, the component must implement a change event for a specific bound property, or notify application settings that the property has changed through the INotifyPropertyChanged interface. If the component does not implement IBindableComponent and you are binding through Visual Studio, the bound properties will be set the first time, but will not update. If the component implements IBindableComponent but does not support property change notifications, the binding will not update in the settings file when the property is changed."
Settings also have restrictions as to what types of objects may be stored. The MSDN article
Application Settings describes it thusly:
"Application settings can be stored as any data type that is XML serializable or has a TypeConverter that implements ToString/FromString. The most common types are String, Integer, and Boolean, but you can also store values [such] as Color, Object, or as a connection string."
This is not a major limitation, though. In the sample code above, you saw objects of type string, DateTime, and ArrayList all worked just fine. I picked the DateTime and ArrayList quite at random, not from any careful perusal of what types might or might not work.