2009-06-19 18 views
26

Tengo una lista <> (mi clase personalizada). Quiero mostrar un elemento específico en esta lista en un cuadro en el control PropertyGrid. Al final de la caja, me gustaría el [...] botón. Al hacer clic, se abriría un formulario que, entre otras cosas, les permitiría elegir uno de los elementos de la Lista. Cuando se cierra, PropertyGrid se actualizará para reflejar el valor seleccionado.¿Cómo crear un elemento editor de PropertyGrid personalizado que abra un formulario?

Cualquier ayuda apreciada.

Respuesta

60

es necesario implementar un referente UITypeEditor, utilizando el servicio IWindowsFormsEditorService para mostrarla:

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); 
    } 
} 

Nota: si necesita acceder a algo en el contexto de la propiedad (el objeto padre, etc.), es decir lo que proporciona el ITypeDescriptorContext (en EditValue); le dice que el PropertyDescriptor y Instance (el MyType) que está involucrado.

+3

¡Ojalá pudiera +1 esto dos veces! Lo volví a subir en el pasado hace casi 2 años y volví a la misma pregunta nuevamente en un proyecto diferente y aún así encontré que era exactamente lo que necesitaba. Gran respuesta, gracias! – Paccc

+0

Todo se ve bien, pero FooEditor no se usa en ningún lado. Debería establecerse como TypeEditor para algunas de las propiedades. – virious

+1

@virious type-editors se puede especificar contra una propiedad o un tipo; en este caso, se aplica (a través de '[Editor (typeof (FooEditor), typeof (UITypeEditor))]') al tipo 'Foo'. Por lo tanto, *** cada propiedad *** de tipo 'Foo' utiliza este editor de forma predeterminada. Ver 'MyType.Foo' en el ejemplo. –

Cuestiones relacionadas