2

I want to show a drop-down of strings in a propertygrid for a selected value. In my current case, I have to bind a dictionary object to a property grid.

If I am binding a class it is easy to do as below using a TypeConverter.

public class Employee
{
    public string Name { get; set; }
    [TypeConverter(typeof(JobCategoryConverter))]
    public int? Category { get; set; }        
}

private void Form1_Load(object sender, EventArgs e)
{
    Employee emp = new Employee() {Name = "Ray" ,Category = 1 };
    propertyGrid1.SelectedObject = emp;
}

result look like this.

enter image description here

Any suggestion how I can show this dropdown if I bind to a dictionary? I used this code to bind dictionary to propertygrid.

So the code looks like,

private void Form1_Load(object sender, EventArgs e)
{
    IDictionary dict = new Hashtable();
    dict["Name"] = "Ray";
    dict["Category"] = 1;

    DictionaryPropertyGridAdapter dpg = new     DictionaryPropertyGridAdapter(dict);
    propertyGrid1.SelectedObject = dpg;
}
Community
  • 1
  • 1
vinayan
  • 1,597
  • 3
  • 19
  • 42
  • Any chance you could share your `JobCatagoryConverter` class? I'm trying to achieve exactly what you could already (i.e. map an ID int to the relevant text). Sadly, you don't include this code. – stigzler Nov 30 '18 at 21:11

1 Answers1

2

This is relatively easy.

The idea is to allow specifying attributes for the custom DictionaryPropertyDescriptor.

First, change the DictionaryPropertyDescriptor class constructor to:

internal DictionaryPropertyDescriptor(IDictionary d, object key, Attribute[] attributes)
    : base(key.ToString(), attributes)
{
    _dictionary = d;
    _key = key;
}

Then add the following to the DictionaryPropertyGridAdapter class:

public Dictionary<string, Attribute[]> PropertyAttributes;

and change the GetProperties method to:

public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
{
    ArrayList properties = new ArrayList();
    foreach (DictionaryEntry e in _dictionary)
    {
        Attribute[] attrs;
        if (PropertyAttributes == null || !PropertyAttributes.TryGetValue(e.Key.ToString(), out attrs))
            attrs = null;
        properties.Add(new DictionaryPropertyDescriptor(_dictionary, e.Key, attrs));
    }

    PropertyDescriptor[] props =
        (PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor));

    return new PropertyDescriptorCollection(props);
}

and you are done with the required changes.

Now you can associate TypeConverter with your "property" similar to what you do with a class like this:

enum JobCategory { Accountant = 1, Engineer, Manager }

class JobCategoryConverter : EnumConverter
{
    public JobCategoryConverter() : base(typeof(JobCategory)) { }
}

private void Form1_Load(object sender, EventArgs e)
{
    IDictionary dict = new Hashtable();
    dict["Name"] = "Ray";
    dict["Category"] = 1;

    DictionaryPropertyGridAdapter dpg = new DictionaryPropertyGridAdapter(dict);
    dpg.PropertyAttributes = new Dictionary<string, Attribute[]>
    {
        { "Category", new Attribute[] { new TypeConverterAttribute(typeof(JobCategoryConverter)) } }
    };
    propertyGrid1.SelectedObject = dpg;
}

and the result will be:

enter image description here

You can also associate other attributes like DisplayName, Category etc.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343