2011-07-30 4 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으로 설정되고 각 항목의 셀 값이 사전에 길이가 인 값으로 설정됩니다.

+0

지금까지 우리는 해당 열에 머리글에 열과 셀 값이 있습니다. 얼마나 많은 세포가 그 컬럼을 가질 것으로 기대합니까? 어디에서 행이 나오는가? – AnthonyWJones

+0

우리는 List 항목이 이고 여기에 5 개의 항목이 들어 있고, 각각은 "GroupA", "GroupB"및 "GroupC"라는 이름 속성을 가진 3 개의 그룹을 갖습니다. 항목 1 : ID : 1에는 GroupA : 100 GroupB가 : 200 GroupC 300 항목 2 : ID : 2에는 GroupA : 1000 GroupB가 : 2000 GroupC 3000 – SiN

+0

확인 다음 5 개 항목은 다음과 같이 나누어진다 조금 생각할지도 모르는 질문. 두 개의 서로 다른'Seats' 인스턴스 (각각이'List '의 멤버)는 "GroupA"라는 이름을 가진 그룹에 대한 각각의 'Values' 사전에 엔트리를 가지고 있습니다. 그들은 둘 다'Group'의 단일 인스턴스를 참조합니까 __or__ 그들 각각은'Id'와'Name'에 대해 같은 값을 갖는'Group'의 다른 인스턴스를 가지고 있습니까? – AnthonyWJones

답변

4

각 그룹 이름에 대해 Group 클래스의 인스턴스가 하나만 있다고 보장 할 수 없다고 가정합니다. (? 다른 당신이 알려진 그룹 목록을 기반으로 열을 생성하는 것입니다 것은 더) 여기

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 방법으로 시작됩니다. 먼저 고유 한 그룹 이름 목록을 가져옵니다. 그룹 이름에 자연스럽게 헤더를 설정하는 각 그룹 이름에 대해 새 텍스트 열을 생성합니다.

열에 바인딩을 설정할 때 이상한 점이 나타납니다. 바인딩에는 변환기가 주어졌으며이 변환기는 SeatsGrid 클래스에서도 구현하기로 결정했습니다. converter 매개 변수는 그룹 이름입니다. 경로가 지정되지 않았기 때문에 바인딩이 실제로 발생할 때 전체 Seats 개체가 변환기로 전달됩니다.

이제 IValueConverter.Convert 방법을 살펴보십시오. converter 매개 변수와 이름이 같은 자리에 Group의 인스턴스 (있는 것)를 찾습니다. 발견되면 반환 할 값을 검색하기위한 키로 Group을 사용합니다.

그룹이 이름별로 고유 한 것으로 알려진 경우 코드는 단순화 될 수 있지만 원칙은 동일합니다.

+0

완벽한! 변환기가 실제로 그것을 수행합니다. 고마워요! – SiN

관련 문제