2011-07-30 11 views
2

SilverlightのDataGridにオブジェクトのコレクションをバインドしたいと思います。目的は、以下のタイプに属する:DictionaryからSilverlightへの列の動的バインドDataGrid

public class Seats 
{ 
    Dictionary<Group, long> dctValues = new Dictionary<Group, long>(); 

    public int Id { get; set; } 

    public Dictionary<Group, long> Values 
    { 
     get { return dctValues; } 
    } 
} 

のに対し、グループはで表されます。

public class Group 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

私は、各列がなければならないグループの辞書に基づいて、列を生成することができるようにしたいですヘッダーはGroup.Nameに設定され、各項目のセル値は辞書のlongの値に等しくなります。

+0

これまでのところ、その列には列とセルの値のヘッダーがあります。列に何個の他のセルがあると思いますか?どこから行が出るのですか? – AnthonyWJones

+0

List に5つの項目が含まれているとします。それぞれには、「GroupA」、「GroupB」、および「GroupC」というnameプロパティを持つ3つのグループがあります。 アイテム1:ID:1、グループA:100、グループB:200、GroupC:300 アイテム2 ID:2、グループA:1000、グループB:2000、GroupC:3000 – SiN

+0

OK次 5つの項目は以下のように分割され少し考えてみるかもしれない質問。 'Seats'の2つの異なるインスタンス(それぞれ、' List 'のメンバー)は、どちらも、名前が「GroupA」であるグループのそれぞれの「Values」辞書にエントリを持っています。彼らはどちらも 'Group'の単一のインスタンスを参照していますか__or__それぞれは' Id'と 'Name'に対して同じ値を持つ' Group'の異なるインスタンスを持っていますか? – AnthonyWJones

答えて

4

私は、グループ名ごとにGroupクラスが1つしか存在しないことを保証することはできません。 (そうでないあなたがいない既知のグループのリストに基づいて列を生成するのでしょうか?)

ここDataGridから派生したクラスです。

public class SeatsGrid : DataGrid, IValueConverter 
{ 
    public SeatsGrid() 
    { 
     AutoGenerateColumns = false; 
    } 
    #region public List<Seats> SeatsList 

    public List<Seats> SeatsList 
    { 
     get { return GetValue(SeatsListProperty) as List<Seats>; } 
     set { SetValue(SeatsListProperty, value); } 
    } 

    public static readonly DependencyProperty SeatsListProperty = 
     DependencyProperty.Register(
      "SeatsList", 
      typeof(List<Seats>), 
      typeof(SeatsGrid), 
      new PropertyMetadata(null, OnSeatsListPropertyChanged)); 

    private static void OnSeatsListPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     SeatsGrid source = d as SeatsGrid; 
     List<Seats> value = e.NewValue as List<Seats>; 
     source.OnSeatsListPropertyChanged(value); 
    } 

    private void OnSeatsListPropertyChanged(List<Seats> value) 
    { 
     ItemsSource = null; 
     Columns.Clear(); 

     var groups = value 
      .SelectMany(seats => seats.Values.Keys) 
      .Select(g => g.Name) 
      .Distinct(); 

     foreach (var group in groups) 
     { 
      DataGridTextColumn col = new DataGridTextColumn(); 
      col.Binding = new Binding() 
      { 
       Converter = this, 
       ConverterParameter = group 
      }; 
      col.Header = group; 
      Columns.Add(col); 
     } 

     ItemsSource = value; 
    } 
    #endregion public List<Seats> SeatsList 

    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     Seats seats = (Seats)value; 
     string group = (string)parameter; 

     Group actualGroup = seats.Values.Keys.FirstOrDefault(g => g.Name == group); 
     if (actualGroup != null) 
     { 
      return seats.Values[actualGroup].ToString(); 
     } 
     else 
     { 
      return null; 
     } 
    } 

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

XAMLに入れ、このクラスのインスタンスを、そのにList<Seats>を割り当てますSeatsListプロパティを使用し、列を生成して行をレンダリングします。

どのように動作しますか?

魔法はOnSeatsListPropertyChangedメソッドで開始します。最初に異なるグループ名のリストを取得します。グループ名ごとに新しいText列を生成し、グループ名に自然にヘッダを設定します。

列のバインディングを設定すると、奇妙なことが表示されます。バインディングには変換器が与えられており、私はSeatsGridクラスに実装することを決定しました。 converterパラメータはグループ名です。パスが指定されていないので、バインディングが実際に発生すると、Seatsオブジェクト全体がコンバーターに渡されます。

IValueConverter.Convertの方法を見てください。コンバータパラメータと同じ名前を持つ座席に、Groupというインスタンスが存在することがわかります。見つかった場合は、返す値を検索するためのキーとしてGroupを使用します。

グループが名前ごとに一意であることが分かっていた場合、コードは簡略化できますが、原則は同じです。

+0

パーフェクト!コンバータは実際にそれを行います。どうもありがとう! – SiN

関連する問題