我将假设我们不能保证每个组名只有一个 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 类上也实现它。转换器参数是组名。由于没有指定路径,所以当绑定实际发生时,整个Seats 对象将被传递给转换器。
现在查看IValueConverter.Convert 方法。它在与转换器参数同名的席位中找到Group 的实例(是任何实例)。 If found 使用 Group 作为键来查找要返回的值。
如果已知组的每个名称都是唯一的,则可以简化代码,但原理相同。