TFS 2010 - Using a TypeConverter to display your custom Process Parameter list type

I just helped someone today with this common problem...

"How do I get my custom list process parameter to show something besides '(Collection)' in the Process Parameter property grid?"

The answer is really simple if you are familiar with the WinForms property grid. The PropertyGrid class looks for type converter attributes on the classes to determine how to display them. For a simple class (not convertable to String), if you don't do anything, it will simply call ToString() to display the text and the text will be readonly. For a list (or really collection), it doesn't call ToString. Rather, it simply displays "(Collection)". Again this value is readOnly.

However, by adding a TypeConverter attribute to your class or list, you can tell the PropertyGrid how to display your type and even how to allow text editing within the Property Grid. Here is a simple example of a List of Strings. That has a type converter that allows the user to type in the list and see the list without needing a custom editor.

Note: This class is just a simple example. For instance, it does not handle strings that have embedded commas.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;

namespace MyCustomProcessParameters
{
    [Serializable]
    [TypeConverter(typeof(ListOfStringsTypeConverter))]
    public class ListOfStrings : List<String>
    {
        public ListOfStrings()
            : base()
        {
        }

        public ListOfStrings(String list)
            : base()
        {
            AddRange(list.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
        }

        public override string ToString()
        {
            return String.Join(",", this);
        }
    }

    internal class ListOfStringsTypeConverter : TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return ((sourceType == typeof(String)) || base.CanConvertFrom(context, sourceType));
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return ((destinationType == typeof(String)) || base.CanConvertTo(context, destinationType));
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (!(value is String))
            {
                return base.ConvertFrom(context, culture, value);
            }

            return new ListOfStrings((String)value);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType != typeof(String) || !(value is ListOfStrings))
            {
                return base.ConvertTo(context, culture, value, destinationType);
            }

            return value.ToString();
        }
    }

}

Here is what it looks like in a test app that has a PropertyGrid:

 In the picture above, you can see that I added three read only properties to my object that allow me to see the individual items in the list.

Note that for TypeConverters to work with your process parameter types, you may need SP1 of TFS 2010 and you may have to make sure your assemblies are in the probing path for Visual Studio.

Happy coding!