Страничные функции

43

Пока что демонстрировалось только то, как передавать информацию странице (за счет программного создания экземпляра страницы, его конфигурирования и последующей передачи методу NavigationService.Navigated), но еще не было показано, как возвращать информацию из страницы. Самый простой (и наименее структурированный) подход — сохранить информацию в какой-то статической переменной приложения, так чтобы она было доступна любому другому классу в программе. Однако такое проектное решение является далеко не самым лучшим, если требуется всего лишь способ для передачи простых фрагментов информации с одной страницы на другую, и не нужно, чтобы эта информация находилась в памяти в течение долгого времени.

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

Другой подход, предлагаемый в WPF, предусматривает применение класса PageFunction. Класс PageFunction представляет собой производную версию класса Page с возможностью возвращения результата. В некоторой степени класс PageFunction напоминает диалоговое окно, в то время как класс Page больше похож на обычное окно.

Чтобы создать PageFunction в Visual Studio, щелкните правой кнопкой мыши на проекте в окне Solution Explorer и выберите в контекстном меню пункт Add --> New Item (Добавить --> Новый элемент). Перейдите в категорию WPF, выберите шаблон Page Function (WPF) (Страничная функция (WPF)), введите имя требуемого файла и щелкните на кнопке Add (Добавить). Код разметки класса PageFunction практически идентичен тому, что используется для класса Page. Единственное отличие в том, что корневым элементом является <PageFunction>, а не <Page>.

Формально PageFunction является полиморфным классом. Он принимает единственный параметр, который указывает, данные какого типа должны использоваться для возвращаемого им значения. По умолчанию для каждого нового класса PageFunction этим параметром является строка (а это означает, что он должен возвращать одну строку). Однако эту деталь можно легко изменить, модифицировав значение атрибута TypeArguments в элементе <PageFunction>.

Ниже приведен пример, в котором класс PageFunction возвращает экземпляр специального класса по имени Product. Для поддержки такой структуры имя соответствующего пространства имен (NavigationApplication) в элементе <PageFunction> отображается на подходящий префикс XML (local), который затем используется при установке значения для атрибута TypeArguments:

<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2 006/xaml"
xmlns:local="clr-namespace:NavigationApplication"
x:Class="NavigationApplication.SelectProductPageFunction"
x:TypeArguments="local:Product"
Title="SelectProductPageFunction" >

Кстати, в случае установки в коде разметки значения для атрибута TypeArguments указывать эту же информацию в объявлении класса не требуется. Вместо этого анализатор XAML будет генерировать правильный класс автоматически. Это означает, что для объявления приведенного выше класса PageFunction вполне достаточно использовать следующий код:

public partial class SelectProductPageFunction: PageFunction<Product>
{ ... }

При создании PageFunction в Visual Studio используется именно такой более явный синтаксис. По умолчанию все новые классы PageFunction, которые создает Visual Studio, наследуются от PageFunction<string>.

Класс PageFunction требует, чтобы все выполняемые в нем процессы навигации обрабатывались программно. Поэтому при щелчке на кнопке или ссылке, приводящей к завершению задачи, код должен вызывать метод PageFunction.OnReturn(). После этого нужно, чтобы предоставлялся либо возвращаемый объект (экземпляр указанного в объявлении класса), либо значение null, указывающее, что задача не была выполнена.

В применении класса PageFunction тоже нет ничего сложного. Вызывающая страница должна создавать экземпляр PageFunction программно из-за необходимости в присоединении обработчика событий к событию PageFunction.Returned. (Этот дополнительный шаг необходим потому, что метод NavigationService.Navigate() является асинхронным и возвращается немедленно.)

SelectProductPageFunction pageFunction = new SelectProductPageFunction();
pageFunction.Return += new ReturnEventHandler<Product>(
SelectProductPageFunction_Returned);
this.NavigationService.Navigate(pageFunction);

Когда пользователь завершает работу с PageFunction и щелкает на ссылке, вызывающей метод OnReturn(), генерируется событие PageFunction.Returned. Возвращаемый объект становится доступным через свойство ReturnEventArgs.Result.

Обычно метод OnReturn() обозначает конец задачи. После этого у пользователя не должно быть возможности возврата обратно к PageFunction. Для этого можно воспользоваться методом NavigationService.RemoveBackEntry(), но имеется более простой подход. Каждый класс PageFunction также имеет свойство по имени RemoveFromJournal. Если установить это свойство в true, страница автоматически удаляется из хронологии при вызове метода OnReturn().

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

Пройди тесты
Лучший чат для C# программистов