Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

PropertyGridEx

2.20/5 (6 votes)
16 Nov 20064 min read 2   1.4K  
A control which extends the functionality of the PropertyGrid.

Introduction

In my last article, I described a control that extends the functionality of the System.Windows.Forms.PropertyGrid. Now, let’s demonstrate the control. This diagram illustrates how the system property grid displays items:

Image 1

Activity Diagram 1

Activity Diagram 1

  1. PropertGrid selects an object derived from the System.ComponentModel.ICustomTypeDescriptor interface used by the SelectedObject property.
  2. PropertGrid invokes the ICustomTypeDescriptor::GetProperties() method and gets the System.ComponentModel.PropertyDescriptorCollection object that contains the collection of System.ComponentModel.PropertyDescriptor objects.
  3. Using the methods and properties of the System.ComponentModel.PropertyDescriptor object, PropertGrid gets the description of each item (for example: display name, value, and others).
  4. If an item contains sub-items, then the PropertyDescriptor object should return an appropriate object derived from the System.ComponentModel.ICustomTypeDescriptor interface that describes a child item, through the GetValue() method. If an item has a simple system type, then this method returns just one.

Examine how the Puma.Controls.PropertyGrid provides the necessary data for the system property grid:

Image 3

Here is a reference of the extended interfaces:

IPropertyGridItemEx is derived from IPropertyGridItem

Provides auxiliary information about the item, most essential being the appropriate PropertyDescriptor object that is used by the property grid for displaying the item (see how the system property grid displays an item).

Has the following properties and methods:

Properties:

  • System.ComponentModel.PropertyDescriptor PropertyDescriptor {get;}

    Returns the PropertyDescriptor object that describes the item.

  • IPropertyGridItemsEx ChildsEx {get;}

    Returns the IPropertyGridItemsEx interface for the item. If the interface has not yet been created, return null.

  • IPropertyGridItemRootEx RootItemEx {get;}

    Returns the root item of the items tree.

  • IPropertyGridItem BaseItem {get;}

    Returns the base IPropertyGridItem interface for this item.

  • int Index {get;}

    Returns the index of the element in the parent’s child fragment collection.

    Remark:

    This is the index relative to the first item in the fragment (see the IPropertyGridChildItemsFragment description), not to the child container (see the IPropertyGridChildItems description).

  • bool IsCategory {get;}

    Returns a flag indicating whether the item represents a category item.

    Remark:

    IsCategory returns true if this item is a sub-root item. In this case, when the property grid is displayed in Category mode and PropertyGrid.FirstItemsAsCategories = true, then the item is displayed as the category for all of its child items.

Methods:

  • IPropertyGridItemsEx CreateChildsEx()

    Creates and returns the IPropertyGridItemsEx interface for the item.

  • string OnValueValidate(string Value);

    Validates the value changed by the user before it is recorded by the property grid. Accepts a new value from the user, validates it, reformats it if necessary, and returns.

IPropertyGridChildItemsEx derived from IPropertyGridChildItems

Properties:

  • System.ComponentModel.PropertyDesriptorCollection PropertyDesriptorCollection {get;}

    Provides appropriately formatted information for the property grid about the child of the item.

Puma.Controls.PropertyGridEx activity diagram:

Activity Diagram 2

Activity Diagram 2

Notice:

  1. When the diagram indicates what should be created for an interface, this means that a class is created that implements this interface (in the Puma.Control.PropertyGridEx project, these classes are PropertyGridChildItemsExImpl and PropertyGridItemExImpl for IPropertyGridChildItemsEx and IPropertyGridItemEx, respectively).

    It is clear that not all sequenced activities that accomplish these interfaces are strictly defined. What is important for the robust functionality of this system is that all members of the base interface are implemented, in what manner does not matter.

  2. PropertyGrid.GetProperties returns a collection which contains a PropertyDescriptor object whose GetValue() method returns a PropertyGridItem object or simply a string value. If it returns a PropertyGridItem object, execute all sequence of actions in the same order, beginning from the PropertyGrid.GetProperties operation.

    When an item displayed by the property grid invokes its methods and properties of the appropriate PropertyDescriptor object (see Activity diagram 1), for the purpose of this project, all these invocations are delegated to the PropertyGridItemEx object (see Activity diagram 2), since we want to change the default representation of an item in the property grid with the appropriate overridden methods and properties of the PropertyGridItemEx object. This is why we need to derive a class from the PropertyGridItemEx class and override the necessary properties.

Example:

C#
public class NewPropertyGridItemExImpl : 
       Puma.Controls.PropertyGrid.PropertyGridItemExImpl
{
    ...
    public override string Value
    {
        get
        {
            //All values in property grid are displayed with 
            //prefix [Changed value representation]
            return "[Changed value representation]" + base.Value;
        }
        set
        {
            base.Value = value;
        }
    }
    ... 

Now implement this class used by the property grid in the place of the base class. This should override the PropertyGridItemRootExImpl, PropertyGridItemExImpl, and PropertyGridChildItemsExImpl classes.

Schematically:

Image 5

To see how this class is implemented in the current project, see the PropertyGridItemExImpl.cs, PropertyGridItemRootExImpl.cs, and the PropertyGridChildItemsExImpl.cs files.

Thanks to Arnie Berg for his contribution in this article writing.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here