2009-01-23 7 views
5

Tengo un PropertyGrid en mi formulario. Mi jefe piensa que es feo. Tosco. No sofisticado.Uso del editor de colecciones .NET sin usar un control de cuadrícula de propiedad

Quiere una forma agradable, pulcra y limpia. Aquí está el truco: una de las propiedades es una colección de nuestros objetos de cosecha propia. Le gusta el editor de colecciones para esta colección.

Sé que puedo crear mi propio editor de colecciones. ¿Pero existe una solución limpia y simple para ahorrarme unas pocas horas de codificación, de modo que pueda crear y usar un editor de colecciones directamente sin usar la cuadrícula de propiedades?

Respuesta

10

usted puede conseguir esta funcionalidad desde el UITypeEditor (a través TypeDescriptor), pero no es trivial - que necesita para configurar una IServiceProvider, un IWindowsFormsEditorService, y lo ideal sería un ITypeDescriptorContext - un poco de faff. Puede ser más simple hacerlo a mano si no está familiarizado con esas herramientas.

Alternativamente, eche un vistazo a SmartPropertyGrid.NET, una alternativa a PropertyGrid.


Actualización: aquí hay un ejemplo de trabajo ... definitivamente no trivial, pero no dude en robar el código. Solo funciona para editores modales, no desplegables. Tampoco es un gran ejemplo de "separación de preocupaciones". La clase MyHelper es la más interesante.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Drawing.Design; 
using System.Windows.Forms; 
using System.Windows.Forms.Design; 
class Foo 
{ 
    public Foo() { Bars = new List<Bar>(); } 
    public List<Bar> Bars { get; private set; } 
} 
class Bar 
{ 
    public string Name { get; set; } 
    public DateTime DateOfBirth { get; set; } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Foo foo = new Foo(); 
     Bar bar = new Bar(); 
     bar.Name = "Fred"; 
     bar.DateOfBirth = DateTime.Today; 
     foo.Bars.Add(bar); 
     Application.EnableVisualStyles(); 
     using(Form form = new Form()) 
     using (Button btn = new Button()) 
     { 
      form.Controls.Add(btn); 
      btn.Text = "Edit"; 
      btn.Click += delegate 
      { 
       MyHelper.EditValue(form, foo, "Bars"); 
      }; 
      Application.Run(form); 
     } 
    } 
} 

class MyHelper : IWindowsFormsEditorService, IServiceProvider, ITypeDescriptorContext 
{ 
    public static void EditValue(IWin32Window owner, object component, string propertyName) { 
     PropertyDescriptor prop = TypeDescriptor.GetProperties(component)[propertyName]; 
     if(prop == null) throw new ArgumentException("propertyName"); 
     UITypeEditor editor = (UITypeEditor) prop.GetEditor(typeof(UITypeEditor)); 
     MyHelper ctx = new MyHelper(owner, component, prop); 
     if(editor != null && editor.GetEditStyle(ctx) == UITypeEditorEditStyle.Modal) 
     { 
      object value = prop.GetValue(component); 
      value = editor.EditValue(ctx, ctx, value); 
      if (!prop.IsReadOnly) 
      { 
       prop.SetValue(component, value); 
      } 
     } 
    } 
    private readonly IWin32Window owner; 
    private readonly object component; 
    private readonly PropertyDescriptor property; 
    private MyHelper(IWin32Window owner, object component, PropertyDescriptor property) 
    { 
     this.owner = owner; 
     this.component = component; 
     this.property = property; 
    } 
    #region IWindowsFormsEditorService Members 

    public void CloseDropDown() 
    { 
     throw new NotImplementedException(); 
    } 

    public void DropDownControl(System.Windows.Forms.Control control) 
    { 
     throw new NotImplementedException(); 
    } 

    public System.Windows.Forms.DialogResult ShowDialog(System.Windows.Forms.Form dialog) 
    { 
     return dialog.ShowDialog(owner); 
    } 

    #endregion 

    #region IServiceProvider Members 

    public object GetService(Type serviceType) 
    { 
     return serviceType == typeof(IWindowsFormsEditorService) ? this : null; 
    } 

    #endregion 

    #region ITypeDescriptorContext Members 

    IContainer ITypeDescriptorContext.Container 
    { 
     get { return null; } 
    } 

    object ITypeDescriptorContext.Instance 
    { 
     get { return component; } 
    } 

    void ITypeDescriptorContext.OnComponentChanged() 
    {} 

    bool ITypeDescriptorContext.OnComponentChanging() 
    { 
     return true; 
    } 

    PropertyDescriptor ITypeDescriptorContext.PropertyDescriptor 
    { 
     get { return property; } 
    } 

    #endregion 
} 
+0

¡No es una broma! Empecé a armar una muestra (hice algo similar a esto en el pasado), y se salió de control bastante rápido. –

Cuestiones relacionadas