y previous article discussed the new Application Settings feature in Windows Forms 2.0. The article demonstrated this feature using C#. However, the application settings feature is also available in Visual Basic. Thus, this article continues my exploration of this new feature, this time round, focusing on how you can automatically bind the application settings to your Windows Forms controls, as well as incorporate application settings into your custom controls.
|Figure 1. Creating an Application Setting: A user-scope FormLocation setting of type System.Drawing.Point.|
Creating Application Settings
Using Visual Studio 2005, create a new Windows application project using Visual Basic and name it as AppSettings. Just as in C#, go to the properties page of a project and create application settings in the Settings tab. Figure 1 shows a user-scope FormLocation setting of type System.Drawing.Point.
To programmatically access the settings during runtime, use the My.Settings namespace, like this:
'---assign a value to the setting--- My.Settings.FormLocation = Me.Location '---access the value of a setting--- Me.Location = My.Settings.FormLocation
Binding Property Grids to User Settings
Instead of writing code to programmatically access the values of application settings, you can directly bind properties of a Windows Forms control to the various application settings you have defined in your application. As an example, let’s now bind the FormLocation setting to the Location property of Form1.
In the Properties window for Form1, expand the (ApplicationSettings) item and in the (PropertyBinding) item, click the “…” button (see Figure 2).
Locate the Location property and in the drop down list next to it, select FormLocation. Click OK.
You can also create new settings in this step. For example, select the BackColor property and in the drop down list next to it, you will realize that there are no settings that match the data type (System.Drawing.Color) of the BackColor property. You can create a new setting at this stage. Simply click on the (New…) link and enter a name for the new setting (see Figure 3).
Using this method of creating a new setting, you do not have to specifically indicate the data type of the setting—it is chosen for you automatically.
Back at the Properties window, you should now see the properties binding of Form1 (Figure 4).
In Form1, add a new Button control and label it as shown in Figure 5.
In the Click event handler for the Button control, code it as follows to allow users to select a color to use as the background color for the form:
Private Sub btnChangeBGColor_Click( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnChangeBGColor.Click Dim cd As New ColorDialog Dim result As DialogResult = cd.ShowDialog If (result = DialogResult.OK) Then '---set background color to the color selected--- Me.BackColor = cd.Color End If End Sub
That’s it! Press F5 to debug the application. Move the form around the screen and then choose a color for the form. Shut down the application by clicking on the “x” button on the form. When you press F5 to debug the application again, notice that the form is displayed at its last position with the background color set to the color you have chosen previously. Notice that you haven’t written any code to save the settings values?
Remember that the application settings are only saved when the application shuts down. To ensure that application settings are saved as and when you want them to, you can do it programmatically:
Changing the User Settings Values Visually During Runtime
Most of the time, you will programmatically manipulate the settings through your code. However, there are times where it is useful to allow your users to modify the values for the settings themselves. For example, you might have a Preferences page that allows users to change the various properties of the application. In this case, you can build your own user interface to allow users to customize the application and then you will manually translate these values into the various application settings.
A better approach is to expose the settings to the user graphically so that users can directly modify their values without you needing to write the extra code. Here is where the PropertyGrid control comes in handy. The PropertyGrid control provides a user interface for browsing and modifying the properties of an object. In this case, we can use it to display the values of our application settings.
In the Toolbox, drag and drop the PropertyGrid control onto Form1.
Double-click on Form1 to switch to its code-behind. In the Form1_Load event, set the SelectedObject property of the PropertyGrid control to My.Settings, like this:
Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load PropertyGrid1.SelectedObject = My.Settings End Sub
Press F5 to debug the application. You will now see the settings shown in the PropertyGrid control (see Figure 6). Best of all, you can directly change their values and the changes will be immediately effected.
|Figure 6. The Setting Shown: View the values of the application settings through the PropertyGrid control..|
By default, the My.Settings object will return all the application settings that you have defined. If you want to display only user-scoped settings, you can do so via the following code snippet:
Private Sub Form1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load PropertyGrid1.SelectedObject = My.Settings '---display only user-scoped settings--- Dim userAttr As New _ System.Configuration.UserScopedSettingAttribute Dim attrs As New _ System.ComponentModel.AttributeCollection(userAttr) PropertyGrid1.BrowsableAttributes = attrs End SubLike-wise, for application-scoped settings:
'---display only application-scoped settings--- Dim appAttr As New _ System.Configuration.ApplicationScopedSettingAttribute Dim attrs As New _ System.ComponentModel.AttributeCollection(appAttr)
Handling Settings Events
Most of the time, you manipulate settings either by assigning values to them or retrieving values from them, and you need not worry about how they work. However, there are four events related to the settings that you can service if you want to look out for certain events. These four events are:
- SettingChanging: Raised before a setting's value is changed.
- PropertyChanged: Raised after a setting's value is changed.
- SettingsLoaded: Raised after the setting values are loaded.
- SettingsSaving: Raised before the setting values are saved.
To service these four events, click on the View Code button in the Settings tab. The Settings.vb file will now appear.
Listing 1 shows the signature of the four event handlers.
|Figure 7. The Result: Tracing the events fired by accessing the application settings.|
To see how the events are fired, add some code to each event handler so that you can trace their flow. Also, check that the user does not set the background color to Black. If s/he does, the BackColor application setting will not be saved (Listing 2)
Press F5 to debug the application. Move the form around and change the background color. You will observe something like that shown in Figure 7 (you can view this through the View | Output window).
Implementing Application Settings for Custom Controls
So far, these discussions have centered on the assumption that you are using settings in standalone applications. What about custom controls? How do you use settings in a custom control?
This section will demonstrate how you can enable your custom controls to make use of settings by following a few simple steps. For simplicity, add a User Control (Add | New Item…) to the project and use the default name of UserControl1.vb.
Populate the user control with the controls shown in (Figure 8).
|Figure 8. The Controls: Populating the user control with these controls.|
This user control allows users to select a range of dates. The dates selected will then be persisted to some application settings.
Switch to UserControl1's code-behind and import the following namespace:
Declare a class named CtrlAppSettings (which inherits from the ApplicationSettingsBase class):
Public NotInheritable Class CtrlAppSettings Inherits ApplicationSettingsBase
_ Public Property StartDate() As Date Get Return Me("StartDate") End Get Set(ByVal value As Date) Me("StartDate") = value End Set End Property _ Public Property EndDate() As Date Get Return Me("EndDate") End Get Set(ByVal value As Date) Me("EndDate") = value End Set End PropertyEnd Class
The ApplicationSettingsBase class is a base class for creating wrapper classes to implement the application settings feature in Window Forms applications. Within the CtrlAppSettings class, there are two properties: StartDate and EndDate. These two properties act as application settings to preserve the range of dates selected in the MonthCalendar control. These two settings are user-scoped, as evident in the
To make use of the application settings defined in the CtrlAppSettings class, declare an instance of the CtrlAppSettings class within the UserControl1 class (Listing 3).
This basically sets the MonthCalendar control to display the dates saved in the application settings.
|Figure 9. Finito!: Locate the user control in Toolbox.|
When the dates in the control is changed, you have to persist the new dates into the application settings. This is achieved in the DateChanged event of the user control (Listing 4).
That's it! Build the project and you should now observe that the UserControl1 is in the Toolbox (see Figure 9).
Drag and drop a copy of the UserControl1 control onto the form. Press F5 to debug the application. Select a range of dates in the user control, shut down the application, and press F5 to debug the application again. You will notice that the dates selected are preserved automatically; proving that the application settings feature is working.
Adding a Second Instance of UserControl1
Now, let's add another instance of UserControl1 onto the form.
Press F5 to debug the application. Select a different range of dates in each control and then shut down the application. Now, when you press F5 to start the application again, you will realize that the two controls display the same range of dates. Why? It turns out that multiple instances of the same control share the same settings class and hence there is only one set of data persisted. Solve this problem by using the SettingsKey property from the ApplicationSettingsBase class.
In the CtrlAppSettings class, add the new SettingsKey property as shown in bold below:
Public NotInheritable Class CtrlAppSettings Inherits ApplicationSettingsBase
_ Public Property StartDate() As Date ... End Property _ Public Property EndDate() As Date ... End Property Public Overloads Property SettingsKey() As String Get Return MyBase.SettingsKey End Get Set(ByVal value As String) MyBase.SettingsKey = value End Set End PropertyEnd Class
In the Load event, assign the SettingsKey for the user control with a value so as to uniquely identify each instance of the control. The easiest way would be to set it to the name of the control, as shown in bold below:
Private Sub UserControl1_Load( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles MyBase.Load '---can select a max. of 60 days--- MonthCalendar1.MaxSelectionCount = 60 '---set the settings key--- ctrlSettings.SettingsKey = Me.Name '---restore the MonthCalendar control to those dates saved in ' settings--- If IsDate(ctrlSettings.StartDate) Then ... End If End Sub
Press F5 to debug the application again. You will now be able to save the different range of dates for each user control.
How does the persisted application settings look like on file? For my application, it is stored in the user.config file in the following directory:
C:Documents and Settings
See Listing 5 to view the XML file.
Knowing how to directly bind your application settings to the various properties on your Windows forms and controls and how to use the application settings feature in your custom controls will hopefully make your life simpler as you write highly customizable applications.