Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
LR_Silverlight.doc
Скачиваний:
1
Добавлен:
10.09.2019
Размер:
829.95 Кб
Скачать

Формирование запросов к службе данных

Сервисы WCF Data Services позволяют выполнять запросы к службе данных из клиентского приложения на основе библиотеки .NET Framework с использованием сформированных клиентских классов службы данных. Клиентская библиотека преобразует запрос, определенный на клиенте как экземпляр класса DataServiceQuery, в сообщение запроса HTTP GET. Библиотека получает ответное сообщение и преобразует его в экземпляры классов клиентской службы данных. Эти классы отслеживаются экземпляром DataServiceContext, которому принадлежит объект DataServiceQuery.

Универсальный класс DataServiceQuery представляет запрос, который возвращает коллекцию экземпляров заданного типа сущности. Запрос к службе данных всегда относится к контексту существующей службы данных. Этот контекст поддерживает URI службы и сведения о метаданных, необходимые для создания и выполнения запроса.

При выполнении запросов можно явно вызывать метод асинхронного вызова BeginExecute с объектом DataServiceQuery<T> или выполнить запрос LINQ к именованному объекту DataServiceQuery<T>, который получен из контекста DataServiceContext.

Использование метода асинхронного вызова BeginExecute

Для загрузки в приложение таблицы Employee базы данных Personal добавим в коде класса MainPage ссылки на библиотеку Data.Services.Client и созданный сервис данных Personal

using System.Data.Services.Client;

using SilverlightAppPersonal.Personal;

а также контекст сущностей context сервиса модели данных EmployeeEntities и экземпляр коллекции employees класса DataServiceCollection<T>

EmployeeEntities context;

DataServiceCollection<Employee> employees;

После внесенных изменений код класса MainPage будет следующим:

using System.Windows.Controls;

using System.Data.Services.Client;

using SilverlightAppPersonal.Personal;

namespace SilverlightAppPersonal

{

public partial class MainPage : UserControl

{

EmployeeEntities context;

DataServiceCollection<Employee> employees;

public MainPage()

{

InitializeComponent();

}

}

}

Класс DataServiceCollection<T> представляет коллекцию динамических сущностей, обеспечивающую выдачу уведомлений при добавлении и удалении из неё элементов или при обновлении списка. Службы данных WCF используют класс DataServiceCollection<T> с целью поддержки привязки извлекаемых из базы данных для элементов управления Silverlight.

При загрузке главной страницы необходимо выполнить следующие подготовительные действия:

создать экземпляр контекста сущностей сервиса модели данных Personal ;

создать экземпляр коллекции employees ;

определить событие загрузки коллекции employees.

Добавим в XAML-код описание события Loaded класса MainPage со ссылкой на обработчик MainPage_Loaded:

Loaded="MainPage_Loaded"

В коде класса MainPage добавим обработчик MainPage_Loaded:

private void MainPage_Loaded(object sender, RoutedEventArgs e)

{

context = new EmployeeEntities(new Uri(

"WfcDataServicePerson.svc", UriKind.Relative));

employees = new DataServiceCollection<Employee>();

employees.LoadCompleted += new

EventHandler<LoadCompletedEventArgs>(employees_LoadCompleted);

ButtonOpen.IsEnabled = true;

}

С учетом того, что при генерации страницы все кнопки создаются как недоступные, то после загрузки необходимо кнопку загрузки данных из базы сделать доступной:

ButtonOpen.IsEnabled = true;

Загрузка данных из базы данных в приложение будет проведена по щелчку кнопки "Загрузить". В XAML-описании добавим для кнопки ButtonOpen обработчик для события Click - Open_Click.

<Button Content="Загрузить" Height="25" Name="ButtonOpen" Margin="35,0,0,0"

Padding="10,5,10,5" Click="Open_Click" />

В код класса MainPage добавим метод Open_Click обработчика события Click кнопки ButtonOpen.

private void Open_Click(object sender, RoutedEventArgs e)

{

ResetBindingData();

DataServiceQuery<Employee> queryEmployee =

context.Employees.AddQueryOption("$orderby", "EmployeeSurname");

try

{

queryEmployee.BeginExecute(OnEmployeeQueryComplete, queryEmployee);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message);

}

}

Метод ResetBindingData() предназначен для очистка коллекции данных employees, списков сотрудников listBoxEmployees и должностей comboBoxTitle:

private void ResetBindingData()

{

employees.Clear();

listBoxEmployees.ItemsSource = null;

comboBoxTitle.ItemsSource = null;

LayoutRoot.UpdateLayout();

}

Далее формируется запрос queryEmployee на получение данных, при этом задается режим сортировки данных по фамилии сотрудника ( EmployeeSurname ):

DataServiceQuery<Employee> queryEmployee =

context.Employees.AddQueryOption("$orderby", "EmployeeSurname");

С помощью метода AddQueryOption в запрос добавляются параметры. Службы данных WCF поддерживают следующие параметры запросов, приведенные в табл. 6.1.

Таблица 7.1. Параметры запросов протокола Open Data

Параметр запроса

Описание

$orderby

Определяет порядок сортировки по умолчанию для сущностей в возвращенном канале

$top

Указывает количество сущностей, которые необходимо включить в возвращаемый канал

$skip

Указывает количество сущностей, которые необходимо пропустить перед возвратом сущностей в канал

$filter

Определяет выражение, фильтрующее сущности, которые возвращаются в канал на основе определенного критерия. Этот параметр запроса поддерживает набор операторов логического сравнения, арифметических операторов и заранее заданных функций запроса, которые используются для оценки критерия фильтра

$expand

Указываются связанные сущности, возвращаемые запросом. Связанные сущности включаются либо в качестве канала, либо в качестве записи, встроенной в сущность, возвращаемую запросом

$format

Указывает формат возвращаемого канала. По умолчанию для каналов задается формат Atom

$select

Указывает проекцию, определяющую свойства сущности, возвращаемые в проекции. По умолчанию в канале возвращаются все свойства сущности

$inlinecount

Запрашивает включение в поток количества сущностей, возвращаемых в канале

Запросы службы данных WCF для Silverlight выполняются асинхронно. Это реализуется методом BeginExecute(), который использует в качестве параметров делегат OnEmployeeQueryComplete и запрос queryEmployee.

queryEmployee.BeginExecute(OnEmployeeQueryComplete, queryEmployee);

Делегат OnEmployeeQueryComplete использует класс Dispatcher для того, чтобы обеспечить асинхронное получение результата в правильном потоке.

private void OnEmployeeQueryComplete(IAsyncResult result)

{

Dispatcher.BeginInvoke(() =>

{

DataServiceQuery<Employee> queryEmployee =

result.AsyncState as DataServiceQuery<Employee>;

try

{

employees.LoadAsync(queryEmployee);

}

catch (DataServiceQueryException ex)

{

MessageBox.Show(string.Format("Ошибка запроса в БД: {0} - {1}",

ex.Response.StatusCode.ToString(), ex.Response.Error.Message));

}

});

}

На данном этапе нам осталось добавить в код класса MainPage делегат employees_LoadCompleted для события LoadCompleted коллекции employees, в котором после завершения формирования коллекции employees задается источник данных для списка listBoxEmployees и производится выделение первого элемента списка.

private void employees_LoadCompleted(object sender, LoadCompletedEventArgs e)

{

if (e.Error == null)

{

if (employees.Continuation != null)

{

employees.LoadNextPartialSetAsync();

}

else

{

listBoxEmployees.ItemsSource = employees;

listBoxEmployees.UpdateLayout();

if (listBoxEmployees.Items.Count > 0)

listBoxEmployees.SelectedIndex = 0;

ButtonOpen.IsEnabled = false;

}

}

else

{

MessageBox.Show(string.Format("Ошибка формирования коллекции: {0}",

e.Error.Message));

ButtonOpen.IsEnabled = true;

}

}

Использование запроса LINQ

Класс DataServiceQuery реализует интерфейс IQueryable, определяемый языком LINQ. Клиентская библиотека службы WCF Data Services может преобразовывать запросы LINQ к данным набора сущностей в URI, который представляет выражение запроса, вычисляемое для ресурса службы данных.

Сформируем запрос LINQ для получения приложением данных сущности Employee.

var allEmpoyees = from emp in context.Employees

orderby emp.EmployeeSurname

select emp;

Формирование коллекции employees класса DataServiceCollection<Employee> для приложения Silverlight может осуществляться только асинхронно, что определяет необходимость использования метода LoadAsync, который требует приведения параметра метода к типу DataServiceQuery<T>, в нашем случае к типу DataServiceQuery<Employee>.

employees.LoadAsync(allEmpoyees as DataServiceQuery<Employee>);

При асинхронной загрузке коллекции employees необходимо сформировать и обработать события загрузки коллекции типа employees.LoadCompleted для сущности Employee и события titles.LoadCompleted для сущности JobTitle.

Для случая использования запроса LINQ метод Open_Click() будет представлен следующим кодом.

private void Open_Click(object sender, RoutedEventArgs e)

{

ResetBindingData();

listBoxEmployees.ItemsSource = null;

comboBoxTitle.ItemsSource = null;

LayoutRoot.UpdateLayout();

try

{

var allEmpoyees = from emp in context.Employees

orderby emp.EmployeeSurname

select emp;

employees.LoadAsync(allEmpoyees as DataServiceQuery<Employee>);

var allTitle = from titl in context.JobTitles

select titl;

titles.LoadAsync(allTitle as DataServiceQuery<JobTitle>);

}

catch (DataServiceClientException ex)

{

MessageBox.Show(ex.Message);

}

}

Следует отметить, что по сравнению с загрузкой данных с использованием метода асинхронного вызова BeginExecute, при применение LINQ-запросов отпадает необходимость использования делегатов OnEmployeeQueryComplete и OnTitleQueryComplete.

http://www.intuit.ru/department/se/dawpfsl/7/4.html

Привязка данных

Для тестирования нашего приложения необходимо сделать привязку списка listBoxEmployees к данным. Для этого используем шаблон DataTemplate.

<ListBox Grid.Row="1" Name="listBoxEmployees" HorizontalAlignment="Center"

Margin="5,2,15,9" Padding="3" Width="364" >

<ListBox.ItemTemplate>

<DataTemplate>

<StackPanel Orientation="Horizontal">

<TextBlock Text="{Binding Path=EmployeeSurname}" />

<TextBlock Text=" " />

<TextBlock Text="{Binding Path=EmployeeName}" />

<TextBlock Text=" " />

<TextBlock Text="{Binding Path=EmployeePatronymic}" />

</StackPanel>

</DataTemplate>

</ListBox.ItemTemplate>

</ListBox>

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

Рис. 7.13.  Фрагмент главной страницы с заполненным списком

Для привязки отображения отдельных данные из списка к детальным данным по сотруднику необходимо для контента основной Grid (LayoutRoot) выполнить привязку к текущему выделению списка listBoxEmployees:

<Grid x:Name="LayoutRoot" Background="White" Margin="10"

VerticalAlignment="Top" Height="590" Width="779"

DataContext="{Binding ElementName=listBoxEmployees, Path=SelectedItem, Mode=TwoWay}">

Начнем привязку детальных данных по сотруднику с текстовых полей: LastName, FirstName, SecondtName и NetName. Для элемента управления TextBox LastName привязка присоединяемого свойства Text к текущему выделению списка listBoxEmployees будет иметь следующий вид:

Text="{Binding Path= EmployeeSurname, Mode=TwoWay}"

Для объекта привязки Binding задается только привязываемое свойство ( Path=EmployeeSurname ), а элемент привязки был ранее определен в контенте основной Grid (свойство DataContext ). Свойство Mode задается значение TwoWay, что определяет двустороннюю привязку. Измененный XAML-код для интерфейсных TextBox примет следующий вид:

<TextBox Name="LastName" Height="25" Margin="5,2,2,2"

Text="{Binding Path=EmployeeSurname, Mode=TwoWay}"></TextBox>

<TextBox Name="FirstName" Height="25" Margin="2"

Text="{Binding Path=EmployeeName, Mode=TwoWay}"></TextBox>

<TextBox Name="SecondtName" Height="25" Margin="2"

Text="{Binding Path= EmployeePatronymic, Mode=TwoWay}"></TextBox>

<TextBox Name="NetName" Height="25" Margin="2"

Text="{Binding Path=NetName, Mode=TwoWay}"></TextBox>

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

Рис. 7.14.  Фрагмент главной страницы с детальными данными

В базе данных Person атрибут EmployeeStatus является целым числом, значение которого соответствует индексу списка ComboBox comboBoxStatus приложения. Функциональность приложения определяет следующий список статуса сотрудника: не задано, активен, выходной, в отпуске, болеет, не работает. Привязка для данного элемента управления выполняется для свойства SelectedIndex.

<ComboBox Name="comboBoxStatus" Height="25" Margin="2"

SelectedIndex = "{Binding Path=EmployeeStatus, Mode=TwoWay, BindsDirectlyToSource=True}">

<ComboBoxItem Content="не задано" />

<ComboBoxItem Content="активен" />

<ComboBoxItem Content="выходной" />

<ComboBoxItem Content="в отпуске" />

<ComboBoxItem Content="болеет" />

<ComboBoxItem Content="не работает" />

<ComboBoxItem Content="помечен как удаленный" />

</ComboBox>

Уровень доступа сотрудника к ресурсам информационной системы – Access в базе данных хранится в виде символьной строки. Однако перечень уровней доступа в системе фиксирован и меняется редко. Для обеспечения работы с ограниченным списком уровней доступа пользователей введем в приложение специальный класс Access. Для этого добавим в приложение SilverlightAppPersonal класс Access, имеющий свойство AccessRole, характеризующее уровень доступа сотрудника к ресурсам сети.

public class Access

{

public string AccessRole { set; get; }

public Access(string accessRole)

{

AccessRole = accessRole;

}

}

В коде класса MainPage добавим ссылку на библиотеку

System.Collections.ObjectModel.

using System.Collections.ObjectModel;

Затем определим коллекцию уровней доступа accesses.

ObservableCollection<Access> accesses;

В коде класса MainPage добавим ссылку на библиотеку System.Collections.ObjectModel.

using System.Collections.ObjectModel;

Затем определим коллекцию уровней доступа accesses.

ObservableCollection<Access> accesses;

В конструкторе класса MainPage создадим экземпляр коллекции accesses и сформируем её из следующего списка: не задано, оператор, старший оператор, начальник смены, администратор, аналитик. Измененный код конструктора класса MainPage приведен ниже.

public MainPage()

{

InitializeComponent();

accesses = new ObservableCollection<Access>();

accesses.Add(new Access("не задано"));

accesses.Add(new Access("оператор"));

accesses.Add(new Access("старший оператор"));

accesses.Add(new Access("начальник смены"));

accesses.Add(new Access("администратор"));

accesses.Add(new Access("аналитик"));

comboBoxAccess.ItemsSource = accesses;

}

После формирования коллекции её значение присваивается источнику данных выпадающего списка comboBoxAccess.

comboBoxAccess.ItemsSource = accesses;

В XAML-коде класса MainPage для выпадающего списка comboBoxAccess добавим привязку для свойства SelectedValue и зададим значение SelectedValuePath для вывода в ComboBox.

<ComboBox Height="25" Name="comboBoxAccess" Margin="5,2,2,2"

SelectedValue="{Binding Path=Access, Mode=TwoWay}"

SelectedValuePath="AccessRole" DisplayMemberPath="AccessRole " />

Должности сотрудников хранятся с отдельной таблице JobTitle базы данных Person. Перед загрузкой в приложение таблицы JobTitle немного усовершенствуем созданный ранее код. В методе Open_Click() всё, что связано с загрузкой в приложение данных таблицы Employee выделим в отдельный метод LoadEmployees():

private void LoadEmployees()

{

DataServiceQuery<Employee> queryEmployee =

context.Employees.AddQueryOption("$orderby", "EmployeeSurname");

try

{

queryEmployee.BeginExecute(OnEmployeeQueryComplete, queryEmployee);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message);

}

}

С учетом введения метода LoadEmployees() метод Open_Click() примет следующий вид:

private void Open_Click(object sender, RoutedEventArgs e)

{

LoadEmployees();

}

Загрузка данных таблицы JobTitle выполняется аналогично загрузке данных таблицы Employee.

Определим в классе MainPage коллекцию titles.

DataServiceCollection<JobTitle> titles;

В методе MainPage_Loaded добавим код создания экземпляра titles коллекции

DataServiceCollection< JobTitle >:

titles = new DataServiceCollection<JobTitle>();

и зарегистрируем для коллекции событие LoadCompleted с делегатом titles_LoadCompleted:

titles.LoadCompleted +=new EventHandler<LoadCompletedEventArgs>(titles_LoadCompleted);

Измененный метод MainPage_Loaded будет иметь следующий вид:

private void MainPage_Loaded(object sender, RoutedEventArgs e)

{

context =

new PersonalEntities(new Uri("WfcDataServicePerson.svc", UriKind.Relative));

employees = new DataServiceCollection<Employee>();

titles = new DataServiceCollection<JobTitle>();

employees.LoadCompleted +=

new EventHandler<LoadCompletedEventArgs>(employees_LoadCompleted);

titles.LoadCompleted +=

new EventHandler<LoadCompletedEventArgs>(titles_LoadCompleted);

ButtonOpen.IsEnabled = true;

}

По аналогии с методом LoadEmployees() создадим метод LoadTitles().

private void LoadTitles()

{

DataServiceQuery<JobTitle> queryTitle = context.JobTitles;

try

{

queryTitle.BeginExecute(OnTitleQueryComplete, queryTitle);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message);

}

}

Далее спроектируем код делегата асинхронного запроса к службе данных.

private void OnTitleQueryComplete(IAsyncResult result)

{

Dispatcher.BeginInvoke(() =>

{

DataServiceQuery<JobTitle> queryTitle = result.AsyncState as DataServiceQuery<JobTitle>;

try

{

titles.LoadAsync(queryTitle);

}

catch (DataServiceQueryException ex)

{

MessageBox.Show(string.Format("Ошибка запроса в БД: {0} - {1}",

ex.Response.StatusCode.ToString(), ex.Response.Error.Message));

}

}

);

}

Делегат обработки события формирования коллекции типа DataServiceCollection<JobTitle> будет иметь следующий вид:

private void titles_LoadCompleted(object sender, LoadCompletedEventArgs e)

{

if (e.Error == null)

{

if (titles.Continuation != null)

{

titles.LoadNextPartialSetAsync();

}

else

{

comboBoxTitle.ItemsSource = titles;

comboBoxTitle.UpdateLayout();

}

}

else

{

MessageBox.Show(string.Format("An error has occured: {0}", e.Error.Message));

}

}

Добавим в код метода Open_Click() вызов метода LoadTitles().

private void Open_Click(object sender, RoutedEventArgs e)

{

LoadEmployees();

LoadTitles();

}

В XAML-коде класса MainPage для выпадающего списка comboBoxTitle добавим привязку для свойства SelectedValue, SelectedValuePath и зададим значение DisplayMemberPath для вывода в ComboBox, а также обработчик события SelectionChanged:

<ComboBox Height="25" Name="comboBoxTitle" Margin="5,2,2,2"

SelectedValue="{Binding Path=JobRoleID, Mode=TwoWay}"

SelectedValuePath="ID" DisplayMemberPath="Title" />

Следует пояснить, что привязка SelectedValue="{Binding Path=JobRoleID, Mode=TwoWay}" и задание свойства для привязки SelectedValuePath="ID" используют поля JobRoleID и ID таблицы Employee через контент Grid, а выводимое в ComboBox значение задается как DisplayMemberPath="Title" и при этом используется атрибут Title таблицы JobTitle коллекции titles, являющейся источником данных для comboBoxTitle.

Для календаря DatePicker необходимо построить привязку для свойства SelectedDate.

<controls:DatePicker Name="datePickerFirstDate"

SelectedDate="{Binding Path=FirstDate, Mode=TwoWay}" Margin="5,2,2,2"/>

<controls:DatePicker Name="datePickerLastDate"

SelectedDate="{Binding Path=LastDate, Mode=TwoWay}" Margin="5,2,2,2" />

На этом привязка данных закончена и можно протестировать приложение. В результате запуска программы страница приложения должна иметь вид, приведенный на рис. 7.15.

Рис. 7.15.  Фрагмент главной страницы с привязанными данными

Управление доступностью кнопок приложения

Silverlight не предлагает встроенную поддержку для модели команд WPF поэтому в разрабатываемом приложении функциональность, связанная с кнопками, должна реализовываться обработчиками событий, а доступность тех или иных кнопок управляться программно.

На странице приложения размещены шесть кнопок: Сохранить, Отменить, Создать, Загрузить, Редактировать и Удалить. Кнопки могут быть доступны или недоступны пользователю при работе приложения. Это задается свойством IsEnable. Доступность кнопок определяется состоянием, в котором находится приложение. В тоже время нажатие какой-либо кнопки переводит, как правило, приложение в какое-либо другое состояние. Для проектируемого приложения можно определить следующие состояния:

первоначальная загрузка страницы (1);

просмотр данных по всем сотрудникам (2);

редактирование данных по отдельному сотруднику (3);

создание новой записи по сотруднику в базе данных (4).

На рис. 7.16 приведена диаграмма состояний приложения, на которой кружками обозначены состояния, а дуги соответствуют переходам при нажатии определенной кнопки.

Рис. 7.16.  Диаграмма состояний приложения

На основе диаграммы состояний построим таблицу доступности кнопок в различных состояниях (таблица 7.2).

Таблица 7.2. Доступность кнопок в различных состояниях приложения

Состояние

Доступность кнопок - IsEnable

Сохранить

Отменить

Создать

Загрузить

Редактировать

Удалить

1

false

false

false

true

false

false

2

false

false

true

false

true

true

3

true

true

false

false

false

false

4

true

true

false

false

false

false

В XAML-коде класса MainPage все кнопки определены как недоступные, то есть свойство IsEnable –false. После загрузки страницы (состояние 1) кнопка Загрузить становится доступной, а после загрузки данных из базы во всех остальных состояниях она недоступна. Режим доступности кнопок Сохранить, Отменить, Создать, Редактировать и Удалить в состояниях 2,3 и 4 изменяется в соответствии данными, приведенными в табл. 6.2. Для управления доступностью кнопок добавим в код класса MainPage метод ButtonIsEnabled().

private void ButtonIsEnabled(bool enabele)

{

ButtonEdit.IsEnabled = enabele;

ButtonSave.IsEnabled = !enabele;

ButtonNew.IsEnabled = enabele;

ButtonUndo.IsEnabled = !enabele;

ButtonDelete.IsEnabled = enabele;

}

Кроме управления доступностью кнопок в приложении целесообразно управлять и возможностью редактирования детальных данных по сотруднику. Детальные данные должны быть доступны для редактирования в состояниях редактирования (3) и создания (4) новой записи, а в режиме просмотра – должны быть доступны только для чтения. Для управления доступностью детальных данных по сотруднику добавим в код класса MainPage метод ReadOnly().

private void ReadOnly(bool readOnly)

{

LastName1.IsReadOnly = !readOnly;

FirstName1.IsReadOnly = !readOnly;

SecondtName1.IsReadOnly = !readOnly;

NetName1.IsReadOnly = !readOnly;

comboBoxTitle.IsEnabled = readOnly;

comboBoxAccess.IsEnabled = readOnly;

comboBoxStatus.IsEnabled = readOnly;

datePickerFirstDate.IsEnabled = readOnly;

datePickerLastDate.IsEnabled = readOnly;

}

В XAML-коде класса MainPage для кнопок Сохранить, Отменить, Создать, Редактировать и Удалить добавим событие Click и обработчики событий Save_Click(), Undo_Click(), New_Click(), Edit_Click() и Delete_Click().

<Button Name="ButtonSave" Content="Сохранить" Margin="5" Padding="5"

Height="25" IsEnabled="False" Click="Save_Click" />

<Button Name="ButtonUndo" Content="Отменить" Margin="5" Padding="5"

Height="25" IsEnabled="False" Click="Undo_Click"/>

<Button Name="ButtonNew" Content="Создать" Margin="5" Padding="5"

Height="25" IsEnabled="False" Click="New_Click"/>

<Button Name="ButtonEdit" Content="Редактировать" Margin="5"

Padding="5" Height="25" IsEnabled="False" Click="Edit_Click"/>

<Button Name="ButtonDelete" Content="Удалить" Padding="5"

Margin="35,0,0,0" Height="25" IsEnabled="False" Click="Delete_Click" />

При нажатии кнопки Удалить не изменяется состояние приложения – это видно из рис. 7.16, где действию Удалить соответствует петля для состояния 2, поэтому на текущем этапе разработки приложения не будем определять код метода и Delete_Click(), а для остальных созданных методов добавим код для управления доступности кнопок и элементов управления.

private void Save_Click(object sender, RoutedEventArgs e)

{

ReadOnly(false);

ButtonIsEnabled(true);

listBoxEmployees.IsEnabled = true;

}

private void Undo_Click(object sender, RoutedEventArgs e)

{

ReadOnly(false);

ButtonIsEnabled(true);

listBoxEmployees.IsEnabled = true;

}

private void Edit_Click(object sender, RoutedEventArgs e)

{

ButtonIsEnabled(false);

listBoxEmployees.IsEnabled = false;

ReadOnly(true);

}

private void New_Click(object sender, RoutedEventArgs e)

{

ButtonIsEnabled(false);

ReadOnly(true);

listBoxEmployees.IsEnabled = false;

}

private void Delete_Click(object sender, RoutedEventArgs e)

{

MessageBoxResult result = MessageBox.Show("Удалить сотрудника: " +

emp.EmployeeSurname + " " + emp.EmployeeName + " " + emp.EmployeePatronymic,

"Предупреждение", MessageBoxButton.OKCancel);

if (result == MessageBoxResult.OK)

{

// Удалить выбранного сотрудника из коллекции данных

}

}

Кроме обработчиков событий кнопок необходимо внести изменения в код метода employees_LoadCompleted(), который завершает загрузку данных из базы по нажатию кнопки Загрузить.

private void employees_LoadCompleted(object sender, LoadCompletedEventArgs e)

{

if (e.Error == null)

{

if (employees.Continuation != null)

{

employees.LoadNextPartialSetAsync();

}

else

{

listBoxEmployees.ItemsSource = employees;

listBoxEmployees.UpdateLayout();

if (listBoxEmployees.Items.Count > 0)

listBoxEmployees.SelectedIndex = 0;

ButtonIsEnabled(true);

ReadOnly(false);

ButtonOpen.IsEnabled = false;

}

}

else

{

MessageBox.Show(string.Format("An error has occured: {0}", e.Error.Message));

ButtonOpen.IsEnabled = true;

}

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]