How to create custom PropertyGrid editor item which opens a form?
Asked Answered
R

1

42

I have a List<> (my custom class). I want to display a specific item in this list in a box on the PropertyGrid control. At the end of the box I would like the [...] button. When clicked, it would open up a form which, among other things, would allow them to pick one of the items from the List. When closed, the PropertyGrid would be updated to reflect the selected value.

Any help appreciated.

Rustice answered 19/6, 2009 at 3:33 Comment(0)
I
99

You need to implement a modal UITypeEditor, using the IWindowsFormsEditorService service to display it:

using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System;

class MyType
{
    private Foo foo = new Foo();
    public Foo Foo { get { return foo; } }
}

[Editor(typeof(FooEditor), typeof(UITypeEditor))]
[TypeConverter(typeof(ExpandableObjectConverter))]
class Foo
{
    private string bar;
    public string Bar
    {
        get { return bar; }
        set { bar = value; }
    }
}
class FooEditor : UITypeEditor
{
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
    {
        return UITypeEditorEditStyle.Modal;
    }
    public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
    {
        IWindowsFormsEditorService svc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
        Foo foo = value as Foo;
        if (svc != null && foo != null)
        {            
            using (FooForm form = new FooForm())
            {
                form.Value = foo.Bar;
                if (svc.ShowDialog(form) == DialogResult.OK)
                {
                    foo.Bar = form.Value; // update object
                }
            }
        }
        return value; // can also replace the wrapper object here
    }
}
class FooForm : Form
{
    private TextBox textbox;
    private Button okButton;
    public FooForm() {
        textbox = new TextBox();
        Controls.Add(textbox);
        okButton = new Button();
        okButton.Text = "OK";
        okButton.Dock = DockStyle.Bottom;
        okButton.DialogResult = DialogResult.OK;
        Controls.Add(okButton);
    }
    public string Value
    {
        get { return textbox.Text; }
        set { textbox.Text = value; }
    }
}
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Form form = new Form();
        PropertyGrid grid = new PropertyGrid();
        grid.Dock = DockStyle.Fill;
        form.Controls.Add(grid);
        grid.SelectedObject = new MyType();
        Application.Run(form);
    }
}

Note: if you need to access something about the context of the property (the parent object etc), that is what the ITypeDescriptorContext (in EditValue) provides; it tells you the PropertyDescriptor and Instance (the MyType) that is involved.

Indoeuropean answered 19/6, 2009 at 4:31 Comment(9)
I wish I could +1 this twice! I upvoted it in the past almost 2 years ago and I came back to the same question again on a different project and still found it to be exactly what I needed. Great answer, thanks!Missioner
Everything looks nice, but FooEditor is not used anywhere. It should be set as TypeEditor for some of the properties.Olwen
@Olwen type-editors can be specified against either a property or a type; in this case it is applied (via [Editor(typeof(FooEditor), typeof(UITypeEditor))]) to the type Foo. Thus every property of type Foo uses this editor by default. See MyType.Foo in the example.Indoeuropean
Is there a way to access the parent window that the grid resides in? Im asking because it would be nice to launch the new window as CenterOwnerKwangtung
Is it possible to get some notification in MyType that the value of foo.Bar has changed ?Hendley
Can anyone tell me how to do this with the WPF Property Grid?Sinistrorse
What is the point of [TypeConverter(typeof(ExpandableObjectConverter))] above the property? I have never used that or seen that when creating UITypeEditor objects.Bardwell
@Bardwell otherwise it doesn't offer the sub-properties in the same wayIndoeuropean
Just tried this approach for a custom DataGridView.Columns property, and it worked. However, when use the smart tag option links "Edit Columns" it just shows me the system default column editor. Is there some way to override this behavior too?Isa

© 2022 - 2024 — McMap. All rights reserved.