Опубликован: 08.07.2011 | Уровень: для всех | Доступ: платный
Лекция 5:

Взаимодействие приложения с базой данных

Привязка выпадающего списка

Привязка данных к колонке типа DataGridComboBoxColumn требует определенной подготовительной работы. В таблице Employee модели данных хранится не текстовое значение должности сотрудника, а внешний ключ для таблицы Title, где находится наименование должности. В EDM-модели можно получить значение атрибута из связанных таблиц. В нашем случае для таблицы Employee имеется атрибут Title.Title1, который посредством имеющихся связей в модели обеспечивает доступ к таблице Title из таблицы Employee. Это можно использовать для просмотра данных по сотруднику, но при редактировании данных необходимо обеспечить выбор должности для сотрудника из списка должностей, которые определены в таблице Title. И это невозможно сделать при привязке колонки Должность к полю Title.Title1.

Для обеспечения возможности работы с коллекцией в таблицы Title в приложении добавим в проект папку Model и в ней создадим класс ListTitle.

public  class ListTitle: ObservableCollection<Title>
{
    public ListTitle()
    {
        ObjectQuery<Title> titles = PageEmployee.DataEntitiesEmployee.Titles;
        var queryTitle = from title in titles select title;
         foreach (Title titl in queryTitle)
        {
            this.Add(titl);
        }
    }
}

Класс ListTitle наследуется от класса обобщенной коллекции ObservableCollection<T> и его назначение создавать коллекцию объектов Title. Поле titles является запросом типа ObjectQuery<Title>. Данному полю присваивается свойство Titles контекста данных DataEntitiesEmployee, который определен в классе PageEmployee. В классе ListTitle не рекомендуется создавать собственный контекст данных, а лучше использовать контекст, созданный в классе PageEmployee. Именно поэтому свойства DataEntitiesEmployee объявлено в классе PageEmployee статическим.

Запрос LINQ получает данные из базы TitlePersonal в поле queryTitle и затем в цикле foreach формируется коллекция класса ListTitle.

Для использования класса ListTitle в XAML-документе класса PageEmployee необходимо объявить данный класс как ресурс. При этом нужно подключить пространство имен WpfApplProject.Model.

xmlns:core ="clr-namespace:WpfApplProject.Model"

Затем определим ресурс страницы с ключом listTitle.

<Page.Resources>
   <core:ListTitle x:Key="listTitle" />
</Page.Resources>

Далее модифицируем XAML описание для типа DataGridComboBoxColumn.

<DataGridComboBoxColumn Header="Должность" 
        ItemsSource="{Binding Source={StaticResource listTitle}}"
        DisplayMemberPath="Title1"
        SelectedValueBinding="{Binding Path=TitleID, Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged}"
        SelectedValuePath="ID" />

Источник выпадающего списка задается как статический ресурс {StaticResource listTitle}. Выводимое в ячейки колонки поле должно соответствовать полю Title1 таблицы Title EDM-модели DisplayMemberPath="Title1"). Выбираемый в списке параметр (SelectedValueBinding) должен быть привязан к полю TitleID таблицы Employee.

SelectedValueBinding="{Binding Path=TitleID, Mode=TwoWay, 
        UpdateSourceTrigger=PropertyChanged}"

Выбор в свойства SelectedValueBinding производится по пути определенному свойством SelectedValuePath (SelectedValuePath="ID").

При запуске приложения страница PageEmployee принимает вид, показанный на рис. 5.8.

Страница PageEmployee с привязанным столбцом "Должность"

увеличить изображение
Рис. 5.8. Страница PageEmployee с привязанным столбцом "Должность"

Ячейка столбца типа DataGridComboBoxColumn имеет три представления ( рис. 5.9). Если ячейка не выделена, то представление обычное текстовое ( рис. 5.9а). При выделении ячейки прорисовывается представление ComboBox ( рис. 5.9б). При раскрытии списка появляется список элемента ComboBox ( рис. 5.9в).

Отображение ComboBox в сетке DataGrid

увеличить изображение
Рис. 5.9. Отображение ComboBox в сетке DataGrid

Привязка даты

При привязке даты к колонке "Дата рождения" ставилась задача для невыделенной ячейки представлять дату в виде цифр дня, месяца и года, разделенных точками, а для выделенной ячейки – использовать класс для выбора даты.

Решение данной задачи осуществлено с помощью разработки двух шаблонов данных DataTemplate.

В первом шаблоне, для которого задан ключ DateTemplate, используется элемент управления TextBlock, свойство Text которого привязывается к атрибуту BirstDate таблицы Employee. Данные в привязке форматируются свойством StringFormat и строковые данные выравниваются по центру. Этот шаблон используется для визуализации данных в режиме их просмотра.

<DataTemplate x:Key="DateTemplate" >
    <TextBlock Text="{Binding BirstDate, 
               StringFormat={}{0:dd\.}{0:MM\.}{0:yyyy}}" 
               VerticalAlignment="Center" HorizontalAlignment="Center" />
</DataTemplate>

Второй шаблон с ключом EditingDateTemplate использует класс DatePicker. Этот шаблон используется в режиме редактирования данных.

<DataTemplate x:Key="EditingDateTemplate">
    <DatePicker SelectedDate="{Binding BirstDate, Mode=TwoWay,
     UpdateSourceTrigger=PropertyChanged}"  />
</DataTemplate>

Разработанные шаблоны необходимо добавить к ресурсам в XAML-документ страницы PageEmployee.

<DataGridTemplateColumn Header="Дата рождения" 
      CellTemplate="{StaticResource DateTemplate}" 
      CellEditingTemplate="{StaticResource EditingDateTemplate}" />

Невыделенную ячейку колонки ( CellTemplate ) свяжим с ресурсом DateTemplate, а редактируемую ячейку ( CellEditingTemplate ) – с ресурсом EditingDateTemplate.

При запуске приложения страница PageEmployee принимает вид, показанный на рис. 5.10.

Страница PageEmployee с привязанным столбцом "Дата рождения"

увеличить изображение
Рис. 5.10. Страница PageEmployee с привязанным столбцом "Дата рождения"

Ячейка столбца для отображения даты типа DataGridTemplateColumn имеет три представления ( рис. 5.11). Если ячейка не выделена, то представление обычное текстовое ( рис. 5.11а). При выделении ячейки прорисовываетася свернутое содержание класса DatePicker ( рис. 5.11б). При щелчке на ячейке появляется календарь ( рис. 5.11в).

Отображение даты в сетке DataGrid

Рис. 5.11. Отображение даты в сетке DataGrid
Александр Петров
Александр Петров

При загрузке данных из БД возникает исключение InvalidOperationException с сообщением: Элемент коллекции должен быть пустым перед использованием ItemsSource. Знаю, что для заполнения DataGrid можно использовать коллекции Items или ItemsSource, но одновременно их использовать нельзя: если задано значение для свойства ItemsSource и в коде C# добавляется элемент в Items, возникает исключение. 
Вопрос, как отследить и отключить добавление элемента в Items?

Максим Спиридонов
Максим Спиридонов

В пятой лекции на второй странице в компиляторе выскакивает ошибка в строчке :

ObjectQuery<Employee> employees = DataEntitiesEmployee.Employees;

Ошибка CS0029

Не удается неявно преобразовать тип "System.Data.Entity.DbSet<WpfApplProject.Employee>" в "System.Data.Entity.Core.Objects.ObjectQuery<WpfApplProject.Employee>".

в using прописал все как положено, здесь похоже именно с преобразованием типов проблемы

Igor Chelyadinski
Igor Chelyadinski
Беларусь, Минск, №54, 2013
Валентина Алешина
Валентина Алешина
Россия