WPF DataGrid. Борьба за Template

от автора

Всем привет!

Надеюсь, своей статьей я внесу ясность в вопросе связки XML представления DataGrid с его кодовым собратом. Для этого лучше всего использовать конкретный пример. Итак, нам необходимо разместить список элементов некоторой структуры в таблице. Допустим сами элементы выглядят в коде следующим образом:

class Element     {        public Element (string firstName, string lastName, string phoneNumber, DateTime date)         {             this.firstName = firstName;             this.lastName = lastName;             this.phoneNumber = phoneNumber;             this.date = date;          }                 public string FirstName { get { return this.firstName; } set { this.firstName = value; } }         public string LastName { get { return this.lastName; } set { this.lastName = value; } }         public string PhoneNumber { get { return this.phoneNumber; } set { this.phoneNumber = value; } }         public DateTime Date { get { return this.date; } set { this.date = value; } }                  private string firstName;         private string lastName;         private string phoneNumber;         private DateTime date;              }

Соответственно, их список будет выглядеть как:

 List<Element> elements = new List<Element>(); 

Теперь перейдем к DataGrid. Так как это все таки WPF, то вытянуть его на форму можно и руками. Пусть IDE сама отпишет для него код.

<DataGrid x:Name="dataGrid" Margin="10,103,0,15"                    CellEditEnding="dataGrid_CellEditEnding" Grid.RowSpan="2" Grid.ColumnSpan="2" HorizontalAlignment="Left" Width="728"                   AutoGenerateColumns="False"/>

Здесь вручную я задал только AutoGenerateColumns=«False», так как в дальнейшем мы будем редактировать колонки таблицы сами.

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

<DataGrid.Columns>                 <DataGridTextColumn Header="Имя" Binding="{Binding Path=FirstName}"/>                 <DataGridTextColumn Header="Фамилия" Binding="{Binding Path=LastName}"/>                 <DataGridTemplateColumn Header="Телефон" SortMemberPath="PhoneNumber">                     <DataGridTemplateColumn.CellTemplate>                         <DataTemplate>                             <TextBox Text="{Binding Path=PhoneNumber}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellTemplate>                     <DataGridTemplateColumn.CellEditingTemplate>                         <DataTemplate>                             <TextBox Text="{Binding Path=PhoneNumber}" />                         </DataTemplate>                     </DataGridTemplateColumn.CellEditingTemplate>                 </DataGridTemplateColumn>                 <DataGridTemplateColumn Header="Дата" SortMemberPath="Date">                     <DataGridTemplateColumn.CellTemplate>                         <DataTemplate >                             <TextBlock Text="{Binding Path=Date, StringFormat='dd/MM/yyyy'}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellTemplate>                     <DataGridTemplateColumn.CellEditingTemplate>                         <DataTemplate>                             <DatePicker SelectedDate="{Binding Date}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellEditingTemplate>                 </DataGridTemplateColumn>                              </DataGrid.Columns> 

Здесь использовано два вида колонок DataGridTextColumn и DataGridTemplateColumn. Про их виды можно почитать везде. Главное здесь понимать, что с помощью DataGridTemplateColumn можно задать любой шаблон. То есть, в ячейки этой колонки можно будет помещать любые элементы управления (кнопки, календари и т.д.). К примеру в третьей колонке это TextBox:

<DataGridTemplateColumn Header="Телефон" SortMemberPath="PhoneNumber">                     <DataGridTemplateColumn.CellTemplate>                         <DataTemplate>                             <TextBox Text="{Binding Path=PhoneNumber}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellTemplate> 

ВАЖНО: Не забывайте прописывать Header, потому что автозаполнение у нас отключено. А также для DataGridTemplateColumn необходимо прописать SortMemberPath, чтобы он знал по какому полю сортировать данные.

Перейдем к Binding. Это непосредственно сама привязка к данным. Ее мы указываем с помощью Binding Path=PhoneNumber. Здесь главное учесть то, что это именно название метода класса, который возвращает значение поля (не phoneNumber, а PhoneNumber, см. описание класса).
И еще один момент. Есть возможность ввести разные типы шаблонов (DataTemplate) для ячеек в обычном состоянии (CellTemplate) и в состоянии редактирования (CellEditingTemplate). В четвертой колонке ячейки в обычном состоянии это TextBox, а в состоянии редактирования DatePicker:

<DataGridTemplateColumn Header="Дата" SortMemberPath="Date">                     <DataGridTemplateColumn.CellTemplate>                         <DataTemplate >                             <TextBlock Text="{Binding Path=Date, StringFormat='dd/MM/yyyy'}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellTemplate>                     <DataGridTemplateColumn.CellEditingTemplate>                         <DataTemplate>                             <DatePicker SelectedDate="{Binding Date}"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellEditingTemplate>                 </DataGridTemplateColumn> 

Также стоит отметить, что при работе с датами у поля Text есть свойство StringFormat, которое можно форматировать. Важно, что для корректного отображения месяца «ММ» должны быть большими.

Теперь, чтобы привязать конкретные данные к таблице вернемся к коду на C#.
После заполнения массива элементами, его надо указать в качестве источника данных:

dataGrid.ItemsSource = elements;

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

dataGrid.Items.Refresh();

.
И в качестве еще одного хорошего примера связки С# — XML, приведу пример проверки заполнения ячеек телефонного номера только цифрами. Для этого немного подредактируем кусок кода третьей колонки:

<DataGridTemplateColumn.CellTemplate>                         <DataTemplate>                             <TextBox Text="{Binding Path=PhoneNumber}" TextChanged="phN_TextChanged"/>                         </DataTemplate>                     </DataGridTemplateColumn.CellTemplate> 

Видно что в теге TextBox я назначил обработчик для события изменения текста. Теперь осталось только прописать этот обработчик в коде:

 private void phN_TextChanged(object sender, TextChangedEventArgs e)         {             int result = 0;             TextBox txtx = sender as TextBox;             if (txtx !=null)             {                 if (!int.TryParse(txtx.Text, out result)) {                     txtx.Text = txtx.Text.Substring(0, txtx.Text.Length - 1);                     txtx.CaretIndex = txtx.Text.Length;                 }             }         }

Проверку на цифры можно сделать и через регулярные выражения.

Всем удачного релиза!

ссылка на оригинал статьи https://habr.com/ru/post/484968/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *