2009-06-03 10 views
7

Mam System.Data.DataRows z kilkoma polami, większość z nich to zwykłe typy typu int, single, string.C#/winforms: jak najlepiej powiązać propertygrid i System.Data.DataRow

jaki jest najlepszy sposób na ich edycję za pomocą właściwości propertygrid? powinien działać automatycznie, bez względu na to, jakie pola ma datarow, ale nie powinien wyświetlać ich wszystkich. Chcę podać listę właściwości, które powinny być ukryte.

ponieważ DataTable jest wygenerowany automatycznie nie mogę dodać własne atrybuty jak [Browsable (false)]

Dzięki wielkie!

+0

Zmieniono przykład; teraz działa na filtrowanie kolumn –

Odpowiedz

14

Edytowany w celu obsługi filtrowania; wiele tricker: oprócz uzyskania DataRowView, musimy dostarczyć niestandardowy składnik, który udaje (poprzez pass-thru PropetyDescriptor s), aby być DataRowView (który sam podszywa się pod DataRow) - i odfiltrować właściwości, które my nie chcę.

Bardzo ciekawy problem ;-P łatwiejsze do rozwiązania w klasycznych klas, ale poniżej działa dla DataRow ;-P

Zauważ, że można robić inne rzeczy w tej dziedzinie, aby niektóre właściwości nieedytowalnych (IsReadOnly) lub mają inny podpis (DisplayName) lub kategorię (Category) - przez zastąpienie innych członków w 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, dziękuję, ale jak mogę ukryć pewne właściwości z tego widoku? na przykład nie chcę, aby zmieniono "identyfikator" tabeli. – clamp

+0

Hmmm ... Trickier ... daj mi chwilę ... –

+0

dziękuję! btw: ponieważ DataTable jest autogenerowane, nie mogę dodawać niestandardowych atrybutów, takich jak [Browsable (false)] – clamp

Powiązane problemy