Как сделать автоматическую генерацию строк и колонок, чтобы получилась таблица
Подскажите пожалуйста.
С помощью каких сигнатур классов и xaml контрола можно реализовать такую таблицу, чтобы:
- Кол-во строк генерировалось автоматически в зависимости от кол-ва значений из источника, например коллекция студентов.
- и автоматически генерировались колонки с названием предметов в зависимости от значений из источника, например коллекция предметов.
- каждая пустая ячейка может принимать данные, чтобы можно было сохранить и показать снова.
- Какие правильные сигнатуры классов использовать, (Класс студент - ФИО, Класс предмет - название предмета, как-то переделать их??).
Как миниатюра.
Ответы (1 шт):
Делается это так
<DataGrid
ItemsSource="{Binding Students, Mode=OneWay}"
AutoGenerateColumns="True"
AutoGeneratingColumn="OnAutoGeneratingColumn"
Количество строк и так будет равно количеству элементов в списке Students
AutoGenerateColumns="True"
обеспечит автогенерацию колонок. Имена настраиваются такprivate void OnAutoGeneratingColumn(object? sender, DataGridAutoGeneratingColumnEventArgs e) { string headername = e.Column.Header.ToString(); //update column details when generating if (headername == "Name") { e.Column.Header = "First Name"; }
В ячейке будет то что есть в источнике. Будет в источнике пусто - значит в ячейке пусто. По умолчанию колонка будет редактируемой (ну текстовая точно). Можно подправить колонку. Она доступна как
e.Column
(пример выше и есть пример правки) или создать полностью свою. Это сложнее, но вот пример.private void OnAutoGeneratingColumn(object? sender, DataGridAutoGeneratingColumnEventArgs e) { string headername = e.Column.Header.ToString(); if (headername == "Age") { var templateColumn = new DataGridTemplateColumn() { Header = "Student Age" }; DataTemplate cardLayout = new DataTemplate(); cardLayout.DataType = typeof(Student); FrameworkElementFactory spFactory = new FrameworkElementFactory(typeof(StackPanel)); spFactory.Name = "factory"; spFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal); FrameworkElementFactory cardHolder = new FrameworkElementFactory(typeof(TextBlock)); cardHolder.SetBinding(TextBlock.TextProperty, new Binding("Age")); cardHolder.SetValue(TextBlock.ToolTipProperty, "Student Age"); spFactory.AppendChild(cardHolder); cardLayout.VisualTree = spFactory; templateColumn.CellTemplate = cardLayout; e.Column = templateColumn; }
Для простоты классы должны быть плоскими вида.
public class Student { public string Name { get; set; } public int Math { get; set; } public int Biology { get; set; } }
Если они таковыми не являются, то можно создать вьюмодель с плоским представлением.. Иначе придется переписывать биндинги в обработчике OnAutoGeneratingColumn
. Ну тут кому что проще.
В общем, в OnAutoGeneratingColumn
настраиваются и имена, и типы и вообще все. Также там можно отменить генерацию какой то колонки (документация)
upd: С порядком несколько сложнее. У колонки есть свойство DisplayIndex
на эту тему, но я с ним дел не имел.