Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Windows Presentation Foundation.docx
Скачиваний:
43
Добавлен:
02.11.2018
Размер:
1.15 Mб
Скачать

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

Маршрутизируемые события (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 – источник события в логическом дереве элементов;

  • OriginalSource – источник события в визуальном дереве элементов;

  • Handled – это значение можно установить в true для остановки маршрутизации события в дереве;

  • RoutedEvent – объект, описывающий маршрутизируемое событие.

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

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

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

С набором элементов, обладающих потоковым родством, связан диспетчер, который принимает методы и ставит их на выполнение в очередь потока элементов. Чтобы элемент мог обладать потоковым родством и иметь доступ к диспетчеру, он должен наследоваться от класса 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()

{

Thread.Sleep(3000); // имитируем работу

// обновим интерфейс

// для этого получаем ссылку на диспетчер (у текущего окна)

// а затем используем метод BeginInvoke()

Dispatcher.BeginInvoke(DispatcherPriority.Normal,

(Action)(() => txt.Text = "Новый текст"));

}

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

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

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

  • DoWork – событие; его обработчик становится асинхронной операцией.

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

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