Design of Control Tables

From Heureka Wiki
Jump to navigation Jump to search

Introduction

A ControlTable is a class whose instances can hold user settings. ControlTables are typically presented in a PropertyGrid, which means that no user interface has to be built for properties with a simple type.

By adding the sttribute Slu.Heureka.BaseLayer.ConfigurationHandling.ControlTable a class is marked as a ControlTable. The system will automatically discover all ControlTables at startup.

Implementation of Control Tables

Creating a new Control Table

Although not required, it is recommended that ControlTables inherit from UndoablePropertyChangedBase. This base class simplifies implementation of the INotifyPropertyChanged interface, which should be used for classes presented in the PropertyGrid.

To add a property of a simple type, follow this example:

public int CleaningVariation {

   get { return _cleaningVariation; }
   [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
   set
   {
       if (value < 0)
           throw new ArgumentOutOfRangeException("value", "CleaningVariation must be >= 0");
       ChangeProperty(ref _cleaningVariation, value);
   }

}

Note the following:

  • NoInlining must be set for the set method, otherwise property changed won't work in release mode
  • Validation can be done before the value is changed
  • UndoablePropertyChangedBase implements ChangeProperty methods with overloads for the most common simple types.

Presentation of Control Tables

Since ControlTables are presented in a PropertyGrid, the attributes in System.ComponentModel aids with the presentation of a ControlTable, such as:

Category
Properties with the same Category are grouped in the PropertyGrid
DisplayName
The DisplayName is the name for the property shown in the PropertyGrid.
Description
The Description is shown at the bottom of the PropertyGrid when the property is selected. The description should give a brief help to the user.
DefaultValue
The DefaultValue is the value set when a new instance of a ControlTable is created. Also, the PropertyGrid shows properties with the default value in a normal font, and properties with a changed value in a bold font.
Browsable
The Browsable attribute can be set to false to hide properties in the property grid (unconditionally, to conditionally hide properties see Hiding Properties Conditionally

In addition to this, a number of additional attributes and type converters are available in the Slu.Heureka.BaseLayer.ComponentModel namespace:

ObjectDefaultValues
Allows default values to be set on other types than simple types
PercentTypeConverter
Presents a property with a fraction (e.g. 0.03) to be presented as a percentage (e.g. 3%)

Hiding Properties Conditionally

If the ControlTable inherits from UndoablePropertyChangedBase, it is easy to hide properties conditionally. Two protected methods can be overriden to hide properties:

GetCategoryNamesToHide
Gets names of entire categories to be hidden
GetPropertyNamesToHide
Gets names of properties to be hidden

Each time the ControlTable is rendered, these two methods are called, and any returned category or property will be hidden from the user.

Using Custom Classes inside a Control Table

Sometimes simple types are not convenient in a ControlTable, and a special class is developed to hold the configuration. There are several considerations when making such a class:

  1. The class must be serializable
  2. The class must be clonable
  3. The ControlTable must have one or more properties with the type of the class
  4. When the control table is cloned, each property with the custom type class must also be cloned
  5. The class may have a custom editor. To use the custom editor, set the Editor attribute for each property
  6. Changes in the custom object must trigger the PropertyChanged event:
    1. If the entire object is changed, it is sufficient to just send the event from the property of the ControlTable (typically this works fine

for custom classes with editors)

    1. If a property is changed inside the object the ControlTable must listen for PropertyChanged from the object, and propagate the event.

Cloning Control Tables

Each ControlTable must implement IClonable.

  • Don't forget to clone reference types (e.g. custom classes inside the ControlTable)
  • If inheriting from another ControlTable, make sure that the base.Clone() is called.

Extending Control Tables

It is possible to extend a ControlTable by inheriting from it. When ControlTables are loaded automatically, only the ControlTable lowest in the inheritance hierarchy will be loaded.