Search code examples
.netwinformspropertygrid

Property Grid create new instance on a property


I'm trying to build a quick administrative interface using the built in Windows.Forms PropertyGrid . I managed to decorate my data classes with the appropriate attributes (ExpandableObjectConverter etc.) and all seems to work fine.

There is a use case I'm not figuring out: When i have values set on complex properties the expand button appears and i can edit the content but when i have a null value there seems to be no way to create a new instance of the desired type. So a solution to this would be of great help. Added bonus if someone knows of a way to present a drop-down to the user of what types it can create from a list of possible derived values.


Solution

  • This is not so complicated, here is a sample code that does this kind of thing:

    public class MyEditor : UITypeEditor
    {
        private IWindowsFormsEditorService _editorService;
    
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }
    
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            if (value != null) // already initialized
                return base.EditValue(context, provider, value);
    
            _editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            ListBox lb = new ListBox();
            lb.SelectionMode = SelectionMode.One;
            lb.SelectedValueChanged += OnListBoxSelectedValueChanged;
    
            // TODO: add your items/logic here
            lb.Items.Add(typeof(TYPE1));
            lb.Items.Add(typeof(TYPE2));
            ....
            lb.Items.Add(typeof(TYPEX));
    
            _editorService.DropDownControl(lb);
            if (lb.SelectedItem == null)
                return base.EditValue(context, provider, value); // no selection, no change
    
            // instantiate an object (add constructor logic if neede)
            return Activator.CreateInstance((Type)lb.SelectedItem);
        }
    
        private void OnListBoxSelectedValueChanged(object sender, EventArgs e)
        {
            _editorService.CloseDropDown();
        }
    }