Wednesday, June 10, 2009

How to Dynamically Customize the Property Window

The on-line help for the Microsoft Visual Studio Domain-Specific Language (DSL) tools explains how to prevent domain properties from appearing in the properties window:

You can prevent domain properties from appearing in the Properties window by setting the Is Browsable property to False. The Is Property Browsable property is available on domain roles.

However, this is a compile-time configuration.  This does not work if you need to optionally display a property based on some runtime state information.

Fortunately, a bit of digging with the most excellent Reflector tool shows that the Microsoft.VisualStudio.Modeling.Design.ElementTypeDescriptor has a virtual method, ShouldCreatePropertyDescriptor, that can be overridden.

Suppose you have a domain class Person with the properties IsMarried and WeddingDate.  You want the WeddingDate property to show in the property window only if the IsMarried property is true.

First, create a ElementTypeDescriptionProvider for the Person domain class:

class PersonTypeDescriptorProviderElementTypeDescriptorProvider    { }

Now, override the CreateTypeDescriptor() method to create a custom type descriptor named PersonTypeDescriptor:

class PersonTypeDescriptorProvider : ElementTypeDescriptionProvider

   {

   protected override ElementTypeDescriptor

        CreateTypeDescriptor(ICustomTypeDescriptor parent, ModelElement element)

     {return new PersonTypeDescriptor(parent, element);}

   }

 

Using the designer, select the Person domain class and a custom attribute of the type TypeDescriptionProvider passing the PersonTypeDescriptorProvider type to its constructor.

Now create the PersonTypeDescriptor class:

class PersonTypeDescriptor : ElementTypeDescriptor

{

    public PersonTypeDescriptor(

        ICustomTypeDescriptor parent,

        ModelElement element) :base(parent, element)

    {

    }

}

 

Finally, override ShouldCreatePropertyDescriptor method:

protected override bool ShouldCreatePropertyDescriptor(ModelElement requestor, DomainPropertyInfo domainProperty)

{

    if (domainProperty.Name == "WeddingDate")

        return ((Person)requestor).IsMarried;

    return base.ShouldCreatePropertyDescriptor(requestor, domainProperty);

}

 

It’s as simple as that.

No comments: