2016-01-15 3 views
1

У меня есть 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, так как это кажется очевидным выбором, но я не смог выполнить то, что вам нужно. Я почти уверен, что должно быть какое-то решение, которое не является полностью «взломанным», но я не понял этого.

Можно ли использовать данные так, как есть, или ObservableCollection необходимо изменить в любом случае? Как мне связать DataGrid как на StartTime, так и на Location? Или я должен заменить DataGrid?

Любая помощь была бы принята с благодарностью!

+0

Возможно, вы хотите поделиться некоторыми из вас уроками и xaml? –

ответ

0

То, что вы пытаетесь сделать, называется поворотным, и, к сожалению, это не так просто сделать, если вы не знаете точные столбцы заранее и хотите собрать все из данных.

Одно из решений заключается в преобразовании ObservableCollection в DataTable каждый раз, когда изменения данных, а затем ваш DataGrid управления связываются с DataTable с AutoGenerateColumns="true".

Класс DataTable существует с ранней версии .NET и не особенно элегантен для использования с современным C#, но он позволяет создавать столбцы «на лету», что является ключевой задачей при повороте данных ,

С учетом сказанного, вот некоторый код, чтобы построить DataTable из ObservableCollction<Performance>:

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}"; 
} 

Что это делает создать «скелет» DataTable сначала извлекая имена столбцов из спектаклей (удостоверяясь нет дубликатов и сортировки по StartTime), а затем добавление этих столбцов в новый DataTable. (Он также добавляет столбец «Местоположение».)

Затем он добавляет все данные в таблицу, перебирая данные, сгруппированные и отсортированные по местоположению.

Вы можете быть уверены, что ваш DataGrid всегда обновляется, подключаясь к событию CollectionChanged.

Предполагается, что ваш класс Performance обладает следующими тремя целыми свойствами: Id, StartTime и Location.

+0

Большое спасибо! Я подробнее рассмотрю ваш ответ завтра – QWERTZdenker

+0

Он работает. Еще раз спасибо :) – QWERTZdenker

Смежные вопросы