将可观察的收藏品整理成时间表

时间:2016-01-15 17:23:43

标签: c# wpf mvvm datagrid

我有一个ObservableCollection<Performance>需要以时间表的方式显示在WPF应用程序中。

演出除此之外还包括 StartTime 位置,应按照以下方式进行组织:

Location | 14h - 15h | 15h - 16h | 16h - 17h | 17h - 18h
---------+-----------+-----------+-----------+----------
Loc #1   | Perf 1    | Perf 2    | Perf 3    | Perf 4
---------+-----------+-----------+-----------+----------
Loc #2   | Perf 5    | ...
---------------------+
...

我的持久层保证没有交叉点,即当有一个性能位于A并且从X点开始时,没有其他人会这样做。

我尝试了几种方法,主要是DataGrid,因为这似乎是显而易见的选择,但我无法完成所需的工作。我很确定必须有某种解决方案不是完全“hacky”但我没有想出来。

是否可以按原样使用数据,或者ObservableCollection是否需要在任何情况下重组?如何设法绑定DataGridStartTime上的Location两者?或者我应该替换DataGrid吗?

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

您所尝试的内容称为透视,不幸的是,如果您事先不知道确切的列并希望从数据中构建所有内容,那就不那么容易了。

一种解决方案是在每次数据更改时将ObservableCollection转换为DataTable,然后让DataGrid控件绑定到DataTable AutoGenerateColumns="true" }。

自{.NET}的早期版本以来,DataTable类一直存在,并且与现代C#一起使用并不是特别优雅,但它确实允许您动态创建列,这是关键挑战转动数据时。

话虽如此,这里有一些代码来构建来自DataTable的{​​{1}}:

ObservableCollction<Performance>

这样做是为了创造一个&#34;骨架&#34; private static DataTable GetPerformances(ObservableCollection<Performance> performances) { var dataTable = GetTableSkeleton(performances); var performanceGroups = performances .GroupBy(x => x.Location) .OrderBy(x => x.Key); foreach (var performanceGroup in performanceGroups) { var dataRow = dataTable.NewRow(); dataRow["Location"] = $"Loc {performanceGroup.Key}"; foreach (var performance in performanceGroup) { var columnName = GetColumnName(performance.StartTime); dataRow[columnName] = $"Perf {performance.Id}"; } dataTable.Rows.Add(dataRow); } return dataTable; } private static DataTable GetTableSkeleton(IEnumerable<Performance> performances) { var timeRanges = performances .Select(x => x.StartTime) .Distinct() .OrderBy(x => x) .Select(x => new DataColumn(GetColumnName(x))) .ToArray(); var dataTable = new DataTable(); dataTable.Columns.Add("Location"); dataTable.Columns.AddRange(timeRanges); return dataTable; } private static string GetColumnName(int startTime) { return $"{startTime}-{startTime + 1}"; } 首先从性能中提取列名称(确保没有重复项并按StartTime排序),然后将这些列添加到新的DataTable。 (它还添加了“位置”列。)

然后,它通过循环分组并按位置排序的数据将所有数据添加到表中。

您可以通过挂钩DataTable事件来确保DataGrid始终保持更新。

这假设您的CollectionChanged类具有以下三个整数属性:PerformanceIdStartTime