What Was I Thinking?

Follies & Foils of .NET Development
posts - 94 , comments - 348 , trackbacks - 0

Hide Custom Activity Properties from the WF Designer & Property Grid

Sometimes too many options is a bad thing. After all just because I create a property in my custom activity doesn't mean I want it displayed on the design surface. 

To Microsoft's credit, most of the design behavior of workflow is customizable and often pluggable, making it possible and practical to extend the user experience.  Microsoft provides a Browseable attribute which can be placed on properties that according to the help file :

 specifies whether a property or event should be displayed in a Properties window.

Placing this attribute on your public property works. sometimes. To be clear, the attribute seems to work but its not always picked up by the compiler.

The other problem with the declarative approach is it forces me to set the visibility of the property once and only once.  This assumes that the browsable value I specify is the value I want all the time.

Consider the case of a sub classed activity.  Maybe in the base class I want to expose the property, but hide it in a sub class.  This isn't a supported scenario using the declarative Browseable attribute (even if it did work).

My preferred way to hide unwanted properties is to hook into the PreFilterProperties method in the activity designer. 

  protected override void PreFilterProperties(IDictionary properties)
        {
            base.PreFilterProperties(properties);
            string[] propertiesToHide = { "Order", "ErrorMessage" };
            ActivityDesignerHelper.HidePropertiesInDesigner(propertiesToHide, properties, this.GetType());
        }

here's the code of my MidePropertiesInDesigner which I liberated from another developer (I'm sorry I dont recall the original source of this code).  I've modified it slightly to override any existing browseable attributes

 public static IDictionary HidePropertiesInDesigner(string[] propertiesToHide,IDictionary properties, Type designerType )
        {
            foreach (string propname in propertiesToHide)
            {
                PropertyDescriptor prop = (PropertyDescriptor)properties[propname];
                if (prop != null)
                {
                    AttributeCollection runtimeAttributes = prop.Attributes;                   
                    bool hasBrowsable = false;
                    for (int i = 0; i < runtimeAttributes.Count; i++ )
                    {
                        BrowsableAttribute browseAttr = runtimeAttributes[i] as BrowsableAttribute;
                        if (browseAttr != null)
                        {
                            hasBrowsable = true;
                            break;
                        }
                    }
                    // make a copy of the original attributes
                    // but make room for one extra attribute
                    Attribute[] attrs = new Attribute[runtimeAttributes.Count + (hasBrowsable?0:1)];
                    //runtimeAttributes.CopyTo(attrs, 0);
                    // now selectively copy the attributes to a new array
                    int attrCnt = 0;
                    for (int i = 0; i < runtimeAttributes.Count; i++)
                    {
                        Attribute attr = runtimeAttributes[i];
                        // if this attribute is the browseable attribute, skip it
                        if (attr is BrowsableAttribute)
                            continue;
                        attrs[attrCnt] = attr;
                        attrCnt++;
                    }

                    // add in a new browseable(false) attribute
                    attrs[runtimeAttributes.Count] = new BrowsableAttribute(false);
                    prop = TypeDescriptor.CreateProperty(designerType, propname, prop.PropertyType, attrs);
                    properties[propname] = prop;
                }
            }
            return properties;

           
        }


The code iterates through the property's existing attributes, ignoring the browsable attribute (if it exists) and then copies them to a new attribute array, inserts the browseable attribute value specified and assigns it back to the property.

This code works 100% of the time for me, and allows me to decide on a case-by-case basis which properties to hide and which ones to show in the design surface.

 

Print | posted on Wednesday, December 12, 2007 10:54 AM | Filed Under [ Windows Workflow Foundation ]

Feedback

No comments posted yet.
Post A Comment
Title:
Name:
Email:
Comment:
Verification:
 

Powered by: