Механизм привязки данных (DataBinding), страница 16

private void FillDictionary ()

{

flags = new Dictionary<string, Bitmap> ();

Assembly ass = Assembly.GetExecutingAssembly();

foreach (string name in ass.GetManifestResourceNames())

{

if (name.ToLower().EndsWith(".gif")) // Ресурс типа.gif помещаем в hashtable

{

string[] tokens = name.Split(new char[] { '.' }); // Имя файла - это имя страны

if (tokens.Length > 1)

flags[tokens[tokens.Length - 2]] = new Bitmap(ass.GetManifestResourceStream(name));

}

}

}

Теперь приступим к разработке первой версии обработчика события CurrentChanged синхронизатора позиций таблицы клиентов. Здесь мы должны добыть часть таблицы заказов, соответствующую выбранному клиенту. Индекс выбранного клиента (CustomerID) можно получить из текущей строки таблицы клиентов и этой информацией обладает синхронизатор customersSource. В первой версии метода мы получим данные без помощи Web-сервиса, мы получим их из файла Orders.xml, копию которого вы должны перенести в папку Data текущего проекта. Во второй версии метода мы сделаем то же самое, но в рамках другого потока, созданного с помощью объекта ordersWorker класса BackgroundWorker. И, наконец, в третьей версии мы запустим все объекты вместе, то есть возложим функцию поиска и фильтрации данных на Web-сервис.

void customersSource_CurrentChanged (object sender, EventArgs e)

{

DataRowView row = customersSource.Current as DataRowView;

if (row != null) // Отображаем флаг страны клиента

{

string country = (string)row["Country"];

if (flags.ContainsKey(country))

pic.Image = flags[country];

//======= Синхронизируем таблицу заказов

ordersSource.DataSource = GetOrders ((string) row["CustomerID"]);

}

}

Итак, мы добыли текущую строку таблицы клиентов, выудили из нее поле Country, выбрали (с его помощью) из ассоциативного массива картинку флага, поместили ее в PictureBox с именем pic, затем выудили поле CustomerID и передали его в метод GetOrders. Метод GetOrders будет временно выполнять функции Web-сервиса, в нем надо обратиться к таблице заказов и выбрать нужные заказы.

private DataView GetOrders (string id)

{

DataSet ds = new DataSet ();

ds.ReadXml ("../../Data/Orders.xml");

DataView view = ds.Tables["Orders"].DefaultView;

view.RowFilter = "CustomerID = '" + id + "'";

return view;

}

Все очень просто, так как класс DataView обладает нужной функциональностью. Он умеет фильтровать и сортировать данные таблиц и каждая таблица в ADO.NET уже имеет объект типа DataView, прикрепленный к ней по умолчанию. Мы лишь настраиваем фильтр этого объекта и говорим, что нам нужны все строки таблицы, поле CustomerID которых равно идентификатору, переданному параметром. Если вы справились с задачей внедрения картинок в ресурсы сборки, то первая версия проекта OrdersClient должна работать осмысленно.

Как внедрить ресурсы

¨  Найдите (в папке курса) файлы типа gif с картинками флагов.

¨  В контекстном меню окна Solution Explorer дайте команду AddNew Folder. Назовите ее Pictures.

¨  Перенесите файлы с картинками a эту папку.

¨  В контекстном меню окна Solution Explorer (над папкой Pictures) выберите команду AddExistingItem. Установите фильтр просмотра (*.*), найдите файлы с картинками, выделите все и нажмите кнопку Add.

¨  В окне Solution Explorer выделите сразу все файлы с картинками и установите для них свойство Embedded Resource.

Запустите приложение и убедитесь, что элементы работают синхронно.

Задействуем работника

В классе формы мы давно объявили объект ordersWorker класса BackgroundWorker и он хочет работать. но мы не удосужились найти ему применение. Покажем, как заставить этого работника выполнить метод GetOrders в рамках другого потока. Поток, который не требует интерфейса пользователя (то есть, не содержит внутри себя цикла выборки сообщений Windows), называется рабочим.