2009-06-03 14 views
7

ho System.Data.DataRows con diversi campi, la maggior parte di loro solo i tipi semplici come int, singolo, string.C#/WinForms: come associare meglio un PropertyGrid e uno System.Data.DataRow

qual è il modo migliore per renderli modificabili utilizzando un propertygrid? dovrebbe funzionare automaticamente indipendentemente dal tipo di campi in cui si trova il datarow, ma non dovrebbe visualizzarli tutti. Voglio fornire un elenco di proprietà che dovrebbero essere nascoste.

dal DataTable è generata automaticamente non posso aggiungere attributi personalizzati come [sfogliabile (false)]

grazie mille!

+0

Esempio modificato; ora funziona per filtrare le colonne –

risposta

14

Modificato per gestire il filtraggio; molto più complicato: oltre a ottenere il DataRowView, dobbiamo fornire un componente personalizzato che finga (tramite pass-thru PropetyDescriptor s) per essere il DataRowView (che è esso stesso che finge di essere il DataRow) - e filtrare le proprietà che noi don non voglio

problema molto interessante ;-P Più facile da risolvere in classi classiche, ma il seguito lavora per DataRow ;-p

Nota che si potrebbe fare altre cose in questo settore per fare alcune delle proprietà non modificabili (IsReadOnly) o una didascalia diversa (DisplayName) o categoria (Category) - ignorando altri membri in 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, grazie, ma come posso nascondere determinate proprietà da questa vista? per esempio non voglio che l'"Id" del tavolo sia cambiato. – clamp

+0

Hmmm ... più complicato ... dammi un momento ... –

+0

grazie! btw: poiché il DataTable è generato automaticamente non posso aggiungere attributi personalizzati come [Navigabile (falso)] – clamp

Problemi correlati