2011-01-17 14 views
9

DataGridViewに表示したい.NETクラスがあり、DGVのDataSourceをオブジェクトに設定するデフォルトのデータバインディングが生成されます私の要件の90%(つまり、パブリックプロパティを正しく出力していて、並べ替えを簡単に追加できます)。WinForms DataGridView - リストプロパティ(列数が可変)を持つオブジェクトへのデータバインド

しかし、私がバインドする必要があるプロパティの1つは、他のデータバインドされた項目の後に別々の列にある必要があるデータを含むリストです。私はこれをどのように実装するのが最善の方法に立ち往生しています。

タイトル:

public class BookDetails 
{ 
    public string Title { get; set; } 
    public int TotalRating { get; set; } 
    public int Occurrence { get; set; } 
    public List<int> Rating { get; set; } 
} 

理想的には、私は、実行時にこのような出力を与えるために数値列の数にその評価プロパティを展開することができるだろう:

私のクラスには、次のようになります|合計評価|発生| R1 | R2 | R3 ... RN

また、合計評価をすべての個別評価の合計として計算すると便利ですが、現時点では問題なく手動で更新しています。

+0

タイプのタイプ記述子(または多分TypeConverter)を実装する必要があります。あなたが何をすべきか分かっているなら、かなり些細なことです。残念ながら、私が書いた素晴らしい例は現在仕事中です。 – leppie

+0

@leppie - TypeConverterはここでは適用されません。実際には、ITypedListはおそらく最も簡単です。その後、TypeDescriptionProvider(型指定されたリストにICustomTypeDescriptorを使用しないので) –

+1

@leppie - フレームワークのこの暗いコーナーで混乱するほど怒っている唯一の2人の愚か者でなければなりません; p –

答えて

18

このようにしますか?

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Windows.Forms; 
public class BookDetails 
{ 
    public string Title { get; set; } 
    public int TotalRating { get; set; } 
    public int Occurrence { get; set; } 
    public List<int> Rating { get; set; } 
} 
class BookList : List<BookDetails>, ITypedList 
{ 

    public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors) 
    { 
     var origProps = TypeDescriptor.GetProperties(typeof(BookDetails)); 
     List<PropertyDescriptor> newProps = new List<PropertyDescriptor>(origProps.Count); 
     PropertyDescriptor doThisLast = null; 
     foreach (PropertyDescriptor prop in origProps) 
     { 

      if (prop.Name == "Rating") doThisLast = prop; 
      else newProps.Add(prop); 
     } 
     if (doThisLast != null) 
     { 
      var max = (from book in this 
         let rating = book.Rating 
         where rating != null 
         select (int?)rating.Count).Max() ?? 0; 
      if (max > 0) 
      { 
       // want it nullable to account for jagged arrays 
       Type propType = typeof(int?); // could also figure this out from List<T> in 
               // the general case, but make it nullable 
       for (int i = 0; i < max; i++) 
       { 
        newProps.Add(new ListItemDescriptor(doThisLast, i, propType)); 
       } 
      } 
     } 
     return new PropertyDescriptorCollection(newProps.ToArray()); 
    } 

    public string GetListName(PropertyDescriptor[] listAccessors) 
    { 
     return ""; 
    } 
} 
class ListItemDescriptor : PropertyDescriptor 
{ 
    private static readonly Attribute[] nix = new Attribute[0]; 
    private readonly PropertyDescriptor tail; 
    private readonly Type type; 
    private readonly int index; 
    public ListItemDescriptor(PropertyDescriptor tail, int index, Type type) : base(tail.Name + "[" + index + "]", nix) 
    { 
     this.tail = tail; 
     this.type = type; 
     this.index = index; 
    } 
    public override object GetValue(object component) 
    { 
     IList list = tail.GetValue(component) as IList; 
     return (list == null || list.Count <= index) ? null : list[index]; 
    } 
    public override Type PropertyType 
    { 
     get { return type; } 
    } 
    public override bool IsReadOnly 
    { 
     get { return true; } 
    } 
    public override void SetValue(object component, object value) 
    { 
     throw new NotSupportedException(); 
    } 
    public override void ResetValue(object component) 
    { 
     throw new NotSupportedException(); 
    } 
    public override bool CanResetValue(object component) 
    { 
     return false; 
    } 
    public override Type ComponentType 
    { 
     get { return tail.ComponentType; } 
    } 
    public override bool ShouldSerializeValue(object component) 
    { 
     return false; 
    } 
} 
static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     var data = new BookList { 
      new BookDetails { Title = "abc", TotalRating = 3, Occurrence = 2, Rating = new List<int> {1,2,1}}, 
      new BookDetails { Title = "def", TotalRating = 3, Occurrence = 2, Rating = null }, 
      new BookDetails { Title = "ghi", TotalRating = 3, Occurrence = 2, Rating = new List<int> {3, 2}}, 
      new BookDetails { Title = "jkl", TotalRating = 3, Occurrence = 2, Rating = new List<int>()}, 
     }; 
     Application.Run(new Form 
     { 
      Controls = { 
       new DataGridView { 
        Dock = DockStyle.Fill, 
        DataSource = data 
       } 
      } 
     }); 

    } 
} 
+0

(私はまた、あなたが*それを必要とするならば、それはチェーンを通じた各呼び出しに続くケース) –

+0

+1私が思っていたより少し涼しい、リスト内のアイテムの量が変動するために:) – leppie

+0

パーフェクト!私の魅力のように働く。ありがとうございます:) – vitorbal

関連する問題