2009-06-03 8 views
7

tengo System.Data.DataRows con varios campos, la mayoría de ellos simples tipos como int, single, string.C#/winforms: la mejor forma de enlazar una propiedad propertygrid y una System.Data.DataRow

¿Cuál es la mejor manera de hacer que se puedan editar usando una cuadrícula de propiedades? debería funcionar automáticamente sin importar qué tipo de campos tenga el datarow, pero no debería mostrarlos todos. Quiero proporcionar una lista de propiedades que deberían estar ocultas.

ya que el DataTable se autogenerado No puedo añadir atributos personalizados como [navegable (falsos)]

muchas gracias!

+0

Ejemplo modificado; ahora funciona para filtrar columnas –

Respuesta

14

Editado para manejar el filtrado; mucho tricker: además de obtener el DataRowView, necesitamos proporcionar un componente personalizado que simule (a través de pass-thru PropetyDescriptor s) que sea el DataRowView (que a su vez pretende ser el DataRow) - y filtrar las propiedades que utilizamos no quiero

problema muy interesante ;-P más fácil de resolver en las clases clásicas, pero el siguiente funciona para DataRow ;-P

Tenga en cuenta que usted podría hacer otras cosas en esta área para hacer algunas de las propiedades no editables (IsReadOnly), o tiene un título diferente (DisplayName) o categoría (Category) - anulando a otros miembros en RowWrapperDescriptor.

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Windows.Forms; 
static class program 
{ 
    [STAThread] 
    static void Main() 
    { 
     DataTable table = new DataTable(); 
     table.Columns.Add("ID", typeof(int)); 
     table.Columns.Add("Foo", typeof(int)); 
     table.Columns.Add("Bar", typeof(string)); 
     table.Columns.Add("Audit", typeof(DateTime)); 

     table.Rows.Add(1, 14, "abc", DateTime.MinValue); 
     DataRow row = table.Rows.Add(2,13,"def", DateTime.MinValue); 
     table.Rows.Add(3, 24, "ghi", DateTime.MinValue); 

     RowWrapper wrapper = new RowWrapper(row); 
     wrapper.Exclude.Add("ID"); 
     wrapper.Exclude.Add("Bar"); 

     Application.EnableVisualStyles(); 
     Application.Run(new Form {Controls = { 
      new PropertyGrid { Dock = DockStyle.Fill, 
       SelectedObject = wrapper}}}); 
    } 
} 

[TypeConverter(typeof(RowWrapper.RowWrapperConverter))] 
class RowWrapper 
{ 
    private readonly List<string> exclude = new List<string>(); 
    public List<string> Exclude { get { return exclude; } } 
    private readonly DataRowView rowView; 
    public RowWrapper(DataRow row) 
    { 
     DataView view = new DataView(row.Table); 
     foreach (DataRowView tmp in view) 
     { 
      if (tmp.Row == row) 
      { 
       rowView = tmp; 
       break; 
      } 
     } 
    } 
    static DataRowView GetRowView(object component) 
    { 
     return ((RowWrapper)component).rowView; 
    } 
    class RowWrapperConverter : TypeConverter 
    { 
     public override bool GetPropertiesSupported(ITypeDescriptorContext context) 
     { 
      return true; 
     } 
     public override PropertyDescriptorCollection GetProperties(
      ITypeDescriptorContext context, object value, Attribute[] attributes) 
     { 
      RowWrapper rw = (RowWrapper)value; 
      PropertyDescriptorCollection props = TypeDescriptor.GetProperties(
       GetRowView(value), attributes); 
      List<PropertyDescriptor> result = new List<PropertyDescriptor>(props.Count); 
      foreach (PropertyDescriptor prop in props) 
      { 
       if (rw.Exclude.Contains(prop.Name)) continue; 
       result.Add(new RowWrapperDescriptor(prop)); 
      } 
      return new PropertyDescriptorCollection(result.ToArray()); 
     } 
    } 
    class RowWrapperDescriptor : PropertyDescriptor 
    { 
     static Attribute[] GetAttribs(AttributeCollection value) 
     { 
      if (value == null) return null; 
      Attribute[] result = new Attribute[value.Count]; 
      value.CopyTo(result, 0); 
      return result; 
     } 
     readonly PropertyDescriptor innerProp; 
     public RowWrapperDescriptor(PropertyDescriptor innerProperty) 
      : base(
       innerProperty.Name, GetAttribs(innerProperty.Attributes)) 
     { 
      this.innerProp = innerProperty; 
     } 


     public override bool ShouldSerializeValue(object component) 
     { 
      return innerProp.ShouldSerializeValue(GetRowView(component)); 
     } 
     public override void ResetValue(object component) 
     { 
      innerProp.ResetValue(GetRowView(component)); 
     } 
     public override bool CanResetValue(object component) 
     { 
      return innerProp.CanResetValue(GetRowView(component)); 
     } 
     public override void SetValue(object component, object value) 
     { 
      innerProp.SetValue(GetRowView(component), value); 
     } 
     public override object GetValue(object component) 
     { 
      return innerProp.GetValue(GetRowView(component)); 
     } 
     public override Type PropertyType 
     { 
      get { return innerProp.PropertyType; } 
     } 
     public override Type ComponentType 
     { 
      get { return typeof(RowWrapper); } 
     } 
     public override bool IsReadOnly 
     { 
      get { return innerProp.IsReadOnly; } 
     } 
    } 
} 
+0

ok, gracias, pero ¿cómo puedo ocultar ciertas propiedades de esta vista? por ejemplo, no quiero que se cambie el "Id" de la tabla. – clamp

+0

Hmmm ... trickier ... dame un momento ... –

+0

¡gracias! por cierto: dado que DataTable se autogenera no puedo agregar atributos personalizados como [Navegable (falso)] – clamp

Cuestiones relacionadas