A PropertyPageSite

So what is a a property page site ? Well many years ago we did a lot of development with COM and one object used was the COM property page object, which took a COM object and displayed the property pages of that object. The basic property page site would only work with a single object which was fine for displaying properties for an ActiveX object in a development environment but lacking if you wanted to create a plugin framework where multiple objects plugged into the framework and supplied multiple property pages. So we took the IPropertyPage site and implemented a property page site which used a treeview to display the various objects and one could expand the tree node to view the various pages for each object.

Anyway, so that's what this document is about, however instead of using COM we're going to use C# and .NET.

Firstly let me state that this object is a close re-implementation of the original design from our COM days, it does not use reflection but instead relies of pre-defined interfaces - the advantage of using interfaces are in speed, we do not need to drill down into the reflection heirarchy to extract information from an object.

Okay we're going to define several interfaces, some of which define the site and others which need to be implemented by the property page objects themselves.

  • IPropertyPageContainer
  • IPropertyPageSite
  • IPropertyPage
  • IPropertyPageCollection

Note: IPropertyPageContainer is for future developments and so currently has no part to play in this project. IPropertyPageCollection is really just a collection that's going to allow us to use strong types and also add a couple of properties to make things gel together in a more coeherent manner. So neither of these interfaces are going to be described further - see the class documentation for more information.

If all you want to do is use the property page site which we have implemented, then all you need to is derive your the PropertyPage object which gives a default implementation of the IPropertyPage interface or if you wish to implement the interface directly then simply derive your Form from the Windows.Forms object and implement the IPropertyPage interface yourself.

IPropertyPage

Let's begin with the IPropertyPage. This is what the users forms should implement to turn a Windows Form into a PropertyPage (as stated above). In the mtbsoftware.Extensible assembly is a PropertyPage object which implements the default property page interfaces and is also derived from Form, so you can simply alter your Windows Forms to be derived from a mtbsoftware.Extensible.PropertyPage and concentrate on the inners of your actual property page, such as edit boxes etc.

IPropertyPage has several methods (see class documentation for full details) which allow the site to move the property page, apply changes, check whether the page is dirty and so on. The object extending PropertyPage or implementing IPropertyPage should obviously override methods (such as IsPageDirty) to tell the site the current status of the page.

Okay an example of a property page might not go amiss now, so here we go:

public class NumberInfo : PropertyPage
{
    private System.Windows.Forms.Label lblName;
    private System.Windows.Forms.TextBox txtName;
    private System.Windows.Forms.CheckBox chkActive;
    private System.Windows.Forms.HelpProvider helpProvider;
    ...
    private void txtName_TextChanged(object sender, System.EventArgs e)
    {
        SetPageDirty(true);
    }

    private void chkActive_CheckedChanged(object sender, System.EventArgs e)
    {
        SetPageDirty(true);
    }
    public override void Apply()
    {
        if(data != null)
        {
            data.name = txtName.Text;
            data.activate = chkActive.Checked;
        }
        base.Apply();
    }
}

That's pretty much all that's required from your property page, the base class PropertyPage handle pretty much everything else for you, So the main areas you concentrate on are the controls which make up your page, passing data in and out of the page, setting the dirty flag when changes are made and finally make changes to your data when the Apply method is called (this will be called by the site when the Apply or OK buttons are pressed in the property page site).

You may notice that we've also got a HelpProvider used within this page, the property page site includes the what's this (?) button as well as a Help button - you can include a HelpProvider and the HelpString for each of your page's controls and when the user presses on the what's this button then selects your control the HelpProvider will display the help string, on top of this you can declare a HelpString for the page itself, when the user clicks on the what's this button then clicks on the name of your page within the treeview of the property page site, you'll see the HelpString for the property page. To ensure that the HelpString isn't displayed when the user clicks on what's this then on your page itself, simply set ShowHelp to false - the property page site is able to read your HelpProvider string for the page and display it's what's this help.

IPropertyPageSite

The IPropertySite object is implemented within the mtbsoftware.FormsEx assembly. The interface (from mtbsoftware.Extensible) is used to define the methods required by a site implementing the IPropertyPageSite, In the PropertyPageSite implementation we create a Form with a treeview (to host multiple property pages) and that standard OK, Cancel, Apply and Help buttons. Also includes is the what's this (?) HelpButton which is used for simple popup help. The PropertyPageSite object handles the display of the property pages (as they are selected from the treeview) and also handles button enabling/disabling as well as the calling of IPropertyPage methods when buttons are pressed.

For most purposes the implementation in mtbsoftware.FormsEx will probably suffice for an implementation however if you find you wish to create a new site then it's also a good starting point to learn the simplest way to build such a site. Alternate sites might be to create a tabbed form like the old ActiveX property page site to host multiple pages within one object or within one category.

Okay, so the site is instantiated and filled with property pages via your application. The application may create groups of pages (a group of pages is displayed as children of a parent tree node). The parent node may itself be a property page - for example to just display information about the pages within the group - or the parent may simply have some text in it which would tend to describe what pages it parents. To instantiate and create the association of pages is very simple, an example follows:

// create the property page site
PropertyPageSite site = new PropertyPageSite();

// set some properties for the site, includes the dialog's name
site.Text = "Options";
site.AllowResizing = true;

// create a group of property pages, General, Documents
// and Environment are all derived from the PropertyPage object
PropertyPageCollection env = new PropertyPageCollection();
env.Add(new General());
env.Add(new Documents());
// we're going to associate a page with the parent node of this group
env.GroupPage = new Environment();
// give the group a title
environment.Title = "Environment";

// create a second group of pages, Language being
// derived from PropertyPage
PropertyPageCollection lang = new PropertyPageCollection();
lang.Add(new Languages());
// Note: we are not supplying a parent level page
lang.Title = "Language";

// place the groups of pages into the site
site.Pages = new object[]{env, lang};
// show the property page site
site.ShowDialog();

One thing to note is that with the second property page collection we do not create a parent level page, thus when the parent node of this group of pages is selected the PropertyPageSite object will simply automatically display the first page within the group.

The PropertyPageSite will call the property page if the Apply or OK buttons are pressed, telling them to Apply any changes. If the Help button is pressed it will call the current page and asking it to display help.

Furthermore the property page site will attempt to resize itself (if AllowResizing is true) to suit the largest property page within the collections passed into it. You should bare this in mind when designing your pages as a page significantly larger than the others will alter the smaller one's to fit the extra space, obviously your layout should be flexible (if possible) to cope with such changes.

That's about it for this article except to say the source for the PropertyPage, PropertyPage site etc. as well as demo application is available download here.

The source is provide without any warranty and may be freely used by you in commercial or non-commercial applications, it would be nice if you mentioned us within your application's about box (for example), but this is not a requirement of any license, all we ask is that the copyright notice be left in each source file and that if you find any problems or make any improvements it'd be nice if you could send them through to us.