Click here to Skip to main content
15,895,746 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hi All

Suppose you created an extender provider for controls as follows:

C#
[ProvideProperty("Information", typeof(Control))]
public class TestExtender:Component, IExtenderProvider
{
    public Information GetInformation(Control extendee) {
       // retrieves information object from a Dictionary<control,> list
    }

    public Information SetInformation(Control extendee, Information information) {
       // adds information to Dictionary<control,> 
    }
}

(other details omitted to focus on the Information object)


The information object would have numerous properties (Title, Text, etc).

When compiled, I add the extender provider to the form, and it adds an Information property to the PropertyGrid as expected.

My question - how do you get the PropertyGrid to add the subproperties of Information to the PropertyGrid?

So, in the PropertyGrid of a Control, say TextBox1, there would be a property Information, and when you click the +, it would display the properties of class Information.

I can't figure out how to do this.
Posted
Updated 8-Sep-11 6:33am
v2

1 solution

This works for a normal UserControl, so it should work for you:
Define the base field, and create a public property for it, with the name of the display property you wish. Include the property Properties as shown below:

C#
private ThumbDisplay thumb = new ThumbDisplay();
[Category("Appearance"),
DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public ThumbDisplay Thumbnails
    {
    get { return thumb; }
    set { thumb = value; }
    }

Create your class for the property, with Properties as shown:

C#
[TypeConverter(typeof(ThumbInfoConverter))]
public class ThumbDisplay
    {
    private int minWidth = 25;

    [NotifyParentProperty(true),
    RefreshProperties(RefreshProperties.Repaint)]
    public int MinWidth
        {
        get { return minWidth; }
        set { minWidth = value; }
        }

    private int initialWidth = 100;

    [NotifyParentProperty(true),
    RefreshProperties(RefreshProperties.Repaint)]
    public int InitialWidth
        {
        get { return initialWidth; }
        set { initialWidth = value; }
        }
    private int maxWidth = 255;

    [NotifyParentProperty(true),
    RefreshProperties(RefreshProperties.Repaint)]
    public int MaxWidth
        {
        get { return maxWidth; }
        set { maxWidth = value; }
        }
    }
}

Create the InfoConverter class for your class:

C#
class ThumbInfoConverter : ExpandableObjectConverter
    {
    /// <summary>
    /// CanConvertFrom specifies data types the converter can convert from.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="t"></param>
    /// <returns></returns>
    public override bool CanConvertFrom(ITypeDescriptorContext context,
                                        Type t)
        {
        if (t == typeof(string))
            {
            return true;
            }
        return base.CanConvertFrom(context, t);
        }
    /// <summary>
    ///ConvertFrom actually implements the conversion.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="info"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public override object ConvertFrom(ITypeDescriptorContext context,
                                       CultureInfo info,
                                       object value)
        {
        if (value is string)
            {
            try
                {
                string s = (string)value;
                //Parse the format "min, initial, max"
                Regex r = new Regex(@"\s*(?<min>\d+),\s*(?<initial>\d+),\s*(?<max>\s*\d+)");
                Match m = r.Match(s);
                if (m.Groups.Count == 4)
                    {
                    // All ok
                    int min = Convert.ToInt32(m.Groups[1].Value);
                    int initial = Convert.ToInt32(m.Groups[2].Value);
                    int max = Convert.ToInt32(m.Groups[3].Value);
                    ThumbDisplay t = new ThumbDisplay();
                    t.MinWidth = min;
                    t.InitialWidth = initial;
                    t.MaxWidth = max;
                    return t;
                    }
                }
            catch { }
            // If you got this far, complain that you
            // could not parse the string.
            throw new ArgumentException("Cannot convert '" + (string)value +
                    "' to type ThumbDisplay \"minimumWidth, initialWidth, "+
                    "maximumWidth\"");
            }
        return base.ConvertFrom(context, info, value);
        }
    /// <summary>
    ///CanConvertTo specifies which data types the converter can convert to.
    /// </summary>
    /// <param name="context"></param>
    /// <param name="culture"></param>
    /// <param name="value"></param>
    /// <param name="destType"></param>
    /// <returns></returns>
    public override object ConvertTo(ITypeDescriptorContext context,
                                     CultureInfo culture,
                                     object value,
                                     Type destType)
        {
        if (destType == typeof(string))
            {
            ThumbDisplay t = (ThumbDisplay)value;
            return string.Format("{0}, {1}, {2}",
                                 t.MinWidth,
                                 t.InitialWidth,
                                 t.MaxWidth);
            }
        return base.ConvertTo(context, culture, value, destType);
        }
    }

In order to provide the sort order for the subproperties yourself, overide the ExpandableObjectConverter GetProperties method:

C#
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context,
    object value,
    Attribute[] attributes)
    {
    return TypeDescriptor.GetProperties(typeof(ThumbDisplay), attributes).Sort(new string[] { "MinWidth", "InitialWidth", "MaxWidth" });
    }
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900