Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Технология Windows Presentation Foundation.docx
Скачиваний:
44
Добавлен:
18.08.2019
Размер:
850.41 Кб
Скачать

4.3. Маршрутизируемые события

Маршрутизируемые события (routed events) – модель событий WPF, созданная для использования в дереве визуальных элементов. При генерации маршрутизируемого события информация о нём может быть передана как родительским, так и дочерним элементам источника событий.

Реализация и использование маршрутизируемых событий имеет много общего со свойствами зависимостей. Рассмотрим в качестве примера реализацию события Click в стандартном элементе управления Button:

public class Button : ButtonBase

{

// статическое поле для маршрутизируемого события

public static RoutedEvent ClickEvent =

EventManager.RegisterRoutedEvent("Click",

RoutingStrategy.Bubble,

typeof (RoutedEventHandler),

typeof (Button));

// экземплярная оболочка события

public event RoutedEventHandler Click

{

add { AddHandler(ClickEvent, value); }

remove { RemoveHandler(ClickEvent, value); }

}

// внутренний метод для генерации события

protected override void OnClick(EventArgs e)

{

RaiseEvent(new RoutedEventArgs(ClickEvent, this));

}

}

Методы AddHandler(), RemoveHandler() и RaiseEvent() – это методы класса UIElement. Листинг показывает, что при регистрации маршрутизируемого события используется метод EventManager.RegisterRoutedEvent(). Одним из аргументов метода является элемент перечисления RoutingStrategy, описывающего стратегию маршрутизации события:

Tunnel – событие генерируется в корневом элементе, затем в каждом дочернем элементе, пока не достигает элемента-источника.

Bubble – событие генерируется в элементе источнике, затем в каждом родительском элементе, вплоть до корня дерева элементов.

Direct – событие генерируется только в элементе-источнике.

Обработчики маршрутизируемых событий принимают аргумент RoutedEventArgs. Этот класс содержит следующие свойства: Source – источник события в логическом дереве элементов; Handled – при установке в true маршрутизации события в дереве прекращается; RoutedEvent – объект, описывающий маршрутизируемое событие.

Класс UIElement определяет множество маршрутизируемых событий, связанных с клавиатурой, мышью, стилусом. Большинство событий используют Bubble-стратегию. Многие Bubble-события имеют сопряжённое Tunnel-событие, которое генерируется перед Bubble-событием (Tunnel-событие отличает префикс Preview в названии).

4.4. Многопоточность в wpf

Элементы WPF, отображаемые в одном окне, обладают потоковым родством (thread affinity). Это означает, что поток, который их создал, владеет ими, а другие потоки не могут взаимодействовать с этими элементами напрямую. С набором элементов, обладающих потоковым родством, связан диспетчер, который принимает методы и ставит их на выполнение в очередь потока элементов. Чтобы элемент мог обладать потоковым родством и иметь доступ к диспетчеру, он должен наследоваться от класса DispatcherObject. Этот класс имеет всего три члена:

Dispatcher – свойство, возвращающее диспетчер потока;

CheckAccess() – метод возвращает true, если код выполняется в потоке элемента;

VerifyAccess() – если вызывающий код находится не в потоке элемента, данный метод генерирует исключение InvalidOperationException.

Диспетчер – это экземпляр класса System.Windows.Threading.Dispatcher. Метод диспетчера BeginInvoke() используется для того, чтобы спланировать код в качестве задачи для диспетчера:

// предположим, что это обработчик нажатия некоторой кнопки

private void btn_Click(object sender, RoutedEventArgs e)

{

// запускаем новый метод в отдельном потоке

new Thread(UpdateTextRight).Start();

}

private void UpdateTextRight()

{

// обновим интерфейс - у диспетчера окна вызываем BeginInvoke()

Dispatcher.BeginInvoke((Action)(() => txt.Text = "New text"));

}

Для организации в приложении WPF асинхронного выполнения можно использовать объект класса System.ComponentModel.BackgroundWorker. Основные элементы этого класса:

RunWorkerAsync() – метод стартует асинхронную операцию. Имеется перегруженная версия, принимающая аргумент асинхронной операции.

CancelAsync() – запрос на отмену асинхронной операции.

DoWork – обработчик этого события будет асинхронной операцией.

RunWorkerCompleted – это событие генерируется, если асинхронная операция завершилась, была отменена или прекращена из-за исключения.

IsBusy – булево свойство; позволяет узнать, выполняется ли операция.