Опубликован: 08.07.2011 | Доступ: свободный | Студентов: 1772 / 93 | Оценка: 4.15 / 4.08 | Длительность: 15:28:00
Лекция 8:

Разработка многофункциональных бизнес-приложений

Разработка клиентской части приложения

Разработаем страницу для отображения списка сотрудников. Добавим в клиентскую часть, в папку Views страницу Silverlight EmployeePage. Для данной страницы в конструкторе откроем вкладку Источник данных и настроим представление данных на странице. Для сущности Employee определим представление в форме DataGrid, для поля Picture – Image, для полей FirstData и FastDate – DatePicker, а для остальных полей – TextBox ( рис. 10.22).

Вкладка Источник данных

Рис. 10.22. Вкладка Источник данных

Перетащим источник данных для таблицы Employee в поле конструктора окна EmployeePage. Результат генерации DataGrid для сущности Employee приведен на рис. 10.23.

Конструктор страницы EmployeePage

увеличить изображение
Рис. 10.23. Конструктор страницы EmployeePage

Добавим на главной странице Home гиперссылку на созданную страницу EmployeePage, указав для контента расширение разметки для ссылки на строку ресурса ApplicationStrings.EmployeePageTitle.

<HyperlinkButton x:Name="Link3" Style="{StaticResource LinkStyle}"
	NavigateUri="/EmployeePage" TargetName="ContentFrame" 
	Content="{Binding Path=ApplicationStrings.EmployeePageTitle, 
	Source={StaticResource ResourceWrapper}}"/>

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

Страница EmployeePage – первоначальный вариант

увеличить изображение
Рис. 10.24. Страница EmployeePage – первоначальный вариант

При выполнении приложения в списке сотрудников не выводится фотография и должность. Для отображения фотографии необходимо сделать преобразование двоичного файла в объект Image. Такое преобразование выполняется с помощью конвектора.

Добавим в папку Helpers клиентского приложения класс конвертора ImageConverter. Аналогичный конвертор использовался в "Разработка Silverlight-приложений" .

Добавим в ресурсы приложения ресурс конвертора с ключом ImageConverter.

<Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Assets/Styles.xaml"/> 
                <ResourceDictionary>
                    <app:ResourceWrapper x:Key="ResourceWrapper" />
                    <app:NotOperatorValueConverter x:Key="NotOperatorValueConverter" />
                    <app:ImageConverter x:Key="ImageConverter" />
                </ResourceDictionary>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>                
    </Application.Resources>

Изменим XAML-описание для столбца Фото сетки employeeDataGrid.

<sdk:DataGridTemplateColumn x:Name="pictureColumn" Header="Фото" Width="SizeToHeader">
  <sdk:DataGridTemplateColumn.CellTemplate>
    <DataTemplate>
       <Image Source="{Binding Path=Picture, 
                  Converter={StaticResource ImageConverter}}" 
                  Margin="1" Stretch="UniformToFill" Height="60" />
    </DataTemplate>
  </sdk:DataGridTemplateColumn.CellTemplate>
</sdk:DataGridTemplateColumn>

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

Для отображения должности сотрудника в сетке employeeDataGrid на странице EmployeePage необходимо при загрузке сущности Employee обеспечить загрузку связанных с ней данных из таблицы Title. Это можно сделать модифицировав метод GetEmployees() класса сервиса данных EmployeeDomainService.

public IQueryable<Employee> GetEmployees()
{
    return this.ObjectContext.Employees.Include("Title").OrderBy(e => e.LastName);
}

В методе GetEmployees() используется класс ObjectContext, который предоставляет возможность выполнять запросы и работать с данными сущности как с объектами. Данный класс обеспечивает взаимодействие с данными как с объектами, которые являются экземплярами типов сущности, определенными в модели EDM.

Метод GetEmployees() возвращает экземпляр класса IQueryable, который представляет типизированный запрос по отношению к концептуальной модели в данном контексте объекта. Класс имеет ряд методов для формирования запросов к модели данных, некоторые из которых приведены в табл. 8.4.

Таблица 10.4. Методы класса ObjectContext
Имя Описание
GroupBy Группирует результаты запроса по заданным критериям.
Include Задает связанные объекты, включаемые в результаты запроса.
Intersect Ограничивает результаты запроса, включая только те, которые вошли в результаты другого запроса объектов.
OrderBy Сортирует результаты запроса по заданным критериям.
Select Ограничивает результаты запроса только теми свойствами, которые определены в заданной проекции.
Skip Сортирует результаты запроса по заданным критериям и пропускает указанное число результатов.
Top Ограничивает результаты запроса указанным числом элементов.
Where Ограничивает запрос результатами, соответствующими определенным критериям фильтрации.

В методе GetEmployees() для сущности Employees используется метод Include() для объединение в запросе сущностей Employees и Titles, а также метод OrderBy() для сортировки результатов запроса по фамилии ( e => e.LastName ).

В XAML-описании колонки Должность сетки employeeDataGrid страницы EmployeePage следует изменить путь привязки, чтобы получить данные о должности ( Title1 ) из сущности Title.

<sdk:DataGridTextColumn x:Name="titleColumn" 
	Binding="{Binding Path=Title.Title1}" 
	Header="Должность" Width="150" />

После компиляции и запуска программы страница EmployeePage примет вид, приведенный на рис. 10.25.

Страница Сотрудники

увеличить изображение
Рис. 10.25. Страница Сотрудники

При загрузке страницы Сотрудники приложения происходит загрузка данных из базы данных, что требует определенного времени. Во время загрузки данных на экране дисплея появляется пустая страница и не понятно работает или нет приложение. Устранение такой неопределенности можно реализовать с помощью класса BusyIndicator, построенного в соответствии с шаблоном проекта. Использование данного класса обеспечивает вывод элемента управления ProgressBar на экран во время выполнения длительной операции.

Объект BusyIndicatorиндикатор длительно выполняемой операции является контейнером, в который необходимо поместить объект, куда должны быть выведены данные в результате выполнения операции. Для разрабатываемого приложения в контейнер BusyIndicatorLoadData поместим сетку employeeDataGrid, которая визуализирует данные о сотрудниках.

<local:BusyIndicator x:Name="BusyIndicatorLoadData"
	IsBusy="{Binding IsLoadingData, ElementName= employeeDomainDataSource}"
	BusyContent="{Binding Path=ApplicationStrings.BusyIndicatorLoadData, 
	Source={StaticResource ResourceWrapper}}" >
	<sdk:DataGrid  Name="employeeDataGrid" . . .>
	....
	</sdk:DataGrid.Columns>
</local:BusyIndicator>

Свойство IsBusy объекта BusyIndicator задает состояние отображения элемента управления ProgressBar. Данное свойство с помощью расширения разметки привязывается к свойству IsLoadingData объекта DomainDataSource – employeeDomainDataSource. Свойство BusyContent определяет строку, которая будет выводиться в элементе управления ProgressBar при его отображении. В расширении разметки для свойства BusyContent используется задание пути ( ApplicationStrings.BusyIndicatorLoadData ) к статическому ресурсу. При загрузке данных на экране будет отображаться элемент управления ProgressBar с текстом "Загрузка данных . . . ", что устранит для пользователя неопределенность состояния системы в процессе формирования данных в кэше приложения ( рис. 10.26).

Индикация загрузки данных

увеличить изображение
Рис. 10.26. Индикация загрузки данных

При разработке дизайна страницы приложения имеются много вариантов визуализации данных. Например, можно реализовать организацию разбиения и перелистывания страниц с использованием объекта DataPager. Добавим в XAML-описание страницы EmployeePage объект DataPager после описания индикатора загрузки данных BusyIndicatorLoadData.

<sdk:DataPager Height="26" HorizontalAlignment="Left" 
	VerticalAlignment="Bottom" Margin="25,0,0,35" 
	Name="dataPager1"  Width="200" 
	Source="{Binding ElementName=employeeDomainDataSource, Path=Data}" 
	PageSize="5" />

Источником данных ( Source ) для объекта DataPager является объект DomainDataSource – employeeDomainDataSource, а свойство PageSize задает количество строк, выводимых на одной странице ( рис. 10.27).

Реализация перелистывания страниц элементом PageSize

увеличить изображение
Рис. 10.27. Реализация перелистывания страниц элементом PageSize
Александр Петров
Александр Петров

При загрузке данных из БД возникает исключение 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 прописал все как положено, здесь похоже именно с преобразованием типов проблемы