Search code examples
c#winformsdata-bindingpropertygrid

Using a Dictionary in a propertygrid


I'd like to edit a list of key value(string, string) items using a propertygrid. When I use a Dictionary<string,string> as type the propertygrid will show a GUI, but it does not seem "enabled", ie. I can't add any items.

Is the Dictionary object supported, or is there any other object with which I could solve this problem?


Solution

  • I have done it following this code in the past:

    class DictionaryPropertyGridAdapter : ICustomTypeDescriptor
    {
        IDictionary _dictionary;
    
        public DictionaryPropertyGridAdapter(IDictionary d)
        {
            _dictionary = d;
        }
    
        public string GetComponentName()
        {
            return TypeDescriptor.GetComponentName(this, true);
        }
    
        public EventDescriptor GetDefaultEvent()
        {
            return TypeDescriptor.GetDefaultEvent(this, true);
        }
    
        public string GetClassName()
        {
            return TypeDescriptor.GetClassName(this, true);
        }
    
        public EventDescriptorCollection GetEvents(Attribute[] attributes)
        {
            return TypeDescriptor.GetEvents(this, attributes, true);
        }
    
        EventDescriptorCollection System.ComponentModel.ICustomTypeDescriptor.GetEvents()
        {
            return TypeDescriptor.GetEvents(this, true);
        }
    
        public TypeConverter GetConverter()
        {
            return TypeDescriptor.GetConverter(this, true);
        }
    
        public object GetPropertyOwner(PropertyDescriptor pd)
        {
            return _dictionary;
        }
    
        public AttributeCollection GetAttributes()
        {
            return TypeDescriptor.GetAttributes(this, true);
        }
    
        public object GetEditor(Type editorBaseType)
        {
            return TypeDescriptor.GetEditor(this, editorBaseType, true);
        }
    
        public PropertyDescriptor GetDefaultProperty()
        {
            return null;
        }
    
        PropertyDescriptorCollection
            System.ComponentModel.ICustomTypeDescriptor.GetProperties()
        {
            return ((ICustomTypeDescriptor)this).GetProperties(new Attribute[0]);
        }
    
        public PropertyDescriptorCollection GetProperties(Attribute[] attributes)
        {
            ArrayList properties = new ArrayList();
            foreach (DictionaryEntry e in _dictionary)
            {
                properties.Add(new DictionaryPropertyDescriptor(_dictionary, e.Key));
            }
    
            PropertyDescriptor[] props =
                (PropertyDescriptor[])properties.ToArray(typeof(PropertyDescriptor));
    
            return new PropertyDescriptorCollection(props);
        }
    }
    
    class DictionaryPropertyDescriptor : PropertyDescriptor
    {
        IDictionary _dictionary;
        object _key;
    
        internal DictionaryPropertyDescriptor(IDictionary d, object key)
            : base(key.ToString(), null)
        {
            _dictionary = d;
            _key = key;
        }
    
        public override Type PropertyType
        {
            get { return _dictionary[_key].GetType(); }
        }
    
        public override void SetValue(object component, object value)
        {
            _dictionary[_key] = value;
        }
    
        public override object GetValue(object component)
        {
            return _dictionary[_key];
        }
    
        public override bool IsReadOnly
        {
            get { return false; }
        }
    
        public override Type ComponentType
        {
            get { return null; }
        }
    
        public override bool CanResetValue(object component)
        {
            return false;
        }
    
        public override void ResetValue(object component)
        {
        }
    
        public override bool ShouldSerializeValue(object component)
        {
            return false;
        }
    }
    
    private void Form1_Load(object sender, System.EventArgs e)
    {
        IDictionary d = new Hashtable();
        d["Hello"] = "World";
        d["Meaning"] = 42;
        d["Shade"] = Color.ForestGreen;
    
        propertyGrid1.SelectedObject = new DictionaryPropertyGridAdapter(d);
    }
    

    Worked well for us.