Navigation:  Application Architecture > Putting it All Together > Designing for Configurability >

Creating the settings class

Previous pageReturn to chapter overviewNext page

The first step in adding configurability to a component is to identify what needs to be persisted.  Continuing our text editor component example, let us suppose that we want to add the ability to turn on and off word wrapping in the text editor, and that this setting should be persisted as a user setting – that is, any time the same user loads the component, they should find that word wrapping is turned on or off exactly as they left it the last time they used it.  The following example takes you through the exercise of adding a .NET settings class and making some modifications to it in order to explain certain parts of the Framework. Note that It is for illustration purposes only and the same end result is achieved by simply adding a "ClearCanvas Settings" class (provided with the SDK).

To start off, we should add a Settings item to the project using the Visual Studio designers with a single boolean setting named WordWrap.

The settings class controls nothing at the moment, so we should hook our text editor component up to the setting.  Set the WordWrap property on the text box using the value from our settings class.

public TextEditorControl(TextEditorComponent component) : base(component)
{
   InitializeComponent();
 
   _component = component;
 
   _txtText.WordWrap = TextEditorSettings.Default.WordWrap;
 
   _txtText.DataBindings.Add("Text", _component,
                             "Text", true,
                             DataSourceUpdateMode.OnPropertyChanged);
 
   _txtFilename.DataBindings.Add("Text", _component,
                                 "Filename", true,
                                 DataSourceUpdateMode.OnPropertyChanged);
 
   _txtWordCount.DataBindings.Add("Text", _component,
                                  "WordCount", true,
                                  DataSourceUpdateMode.OnPropertyChanged);
 
   _btnSave.Click += delegate(object sender, EventArgs args) { _component.Save(); };
 
   _btnCancel.Click += delegate(object sender, EventArgs args) { _component.Cancel(); };
}

 

Any settings stored using such a class go to the user's profile on the local file system by default, but the framework has an extension point that allows a plugin to provide storage for settings elsewhere, such as on a central server.  In most cases, using this mechanism would be preferable since you gain the potential for roaming user-profiles and centralized administration – with the right plugin for that extension point.  In order to take advantage of that potential, we shall modify our settings class to use such a plugin where available.  Opening the code for the settings class reveals some designer-generated stubs.

using System.ComponentModel;

using System.Configuration;

 

namespace MyPlugin.TextEditor

{

   // This class allows you to handle specific events on the settings class:

   //  The SettingChanging event is raised before a setting's value is changed.

   //  The PropertyChanged event is raised after a setting's value is changed.

   //  The SettingsLoaded event is raised after the setting values are loaded.

   //  The SettingsSaving event is raised before the setting values are saved.

   internal sealed partial class TextEditorSettings

   {

      public TextEditorSettings()

      {

         // // To add event handlers for saving and changing settings, uncomment the lines below:

         //

         // this.SettingChanging += this.SettingChangingEventHandler;

         //

         // this.SettingsSaving += this.SettingsSavingEventHandler;

         //

      }

 

      private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e)

      {

         // Add code to handle the SettingChangingEvent event here.

      }

 

      private void SettingsSavingEventHandler(object sender, CancelEventArgs e)

      {

         // Add code to handle the SettingsSaving event here.

      }

   }

}

 

We need to override the provider of settings storage, so we add the SettingsProvider attribute to the class and specify the StandardSettingsProvider.  In the constructor, we add a line to register the settings object with the ApplicationSettingsRegistry in order to receive notification of change events.

using System.Configuration;

using ClearCanvas.Common.Configuration;

using ClearCanvas.Desktop;

 

namespace MyPlugin.TextEditor

{

   [SettingsGroupDescription("Stores settings for the text editor.")]

   [SettingsProvider(typeof (StandardSettingsProvider))]

   internal sealed partial class TextEditorSettings

   {

      public TextEditorSettings()

      {

         ApplicationSettingsRegistry.Instance.RegisterInstance(this);

      }

   }

}

 
Now, a settings class alone is not very useful, since there is no graphical user interface for it to allow the user to change the setting at runtime.  Luckily for us, using the StandardSettingsProvider and ApplicationSettingsRegistry also has the effect of making our settings accessible through the generic configuration interface found under Tools > Utilities > Configure Settings.

This interface is rather spartan, which would suffice if these settings controlled advanced parameters that generally wouldn't be modified by end users.  However, end users would likely want to be able to control the word wrap feature, so we would have to add a proper user interface in the Options dialog.