Общие сведения о структурной навигации
Содержимое, которое может размещаться в Приложение обозревателя XAML (XBAP), Frame, или NavigationWindow состоит из страниц, которые могут быть идентифицированы пакетом универсальные идентификаторы ресурсов (URI) и просматриваться с помощью гиперссылок. Структура страниц и способы навигации по ним с помощью гиперссылок называется топологией навигации. Такая топология подходит для различных типов приложений, особенно тех, в которых необходим переход по документам. В таких приложениях пользователь может перемещаться с одной страницы на другую даже при отсутствии связи между ними.
Тем не менее другие типы приложений содержат страницы, которым необходимо ссылаться друг на друга. Например, рассмотрим приложение управления персоналом, в котором есть одна страница со списком всех сотрудников организации — страница "Список сотрудников". На этой странице пользователи также могут добавить нового сотрудника, щелкнув гиперссылку. При ее щелчке открывается новая страница "Добавить сотрудника", на которой собираются сведения о новом сотруднике и возвращаются на страницу "Список сотрудников". При этом создается новый сотрудник и обновляется список. Этот стиль навигации аналогичен вызову метода для выполнения обработки и возврата значения, который называется структурным программированием. Таким образом, этот стиль навигации называется структурной навигацией.
Page Класс не реализует поддержку структурной навигации. Вместо этого PageFunction<T> класс является производным от Page и расширяет его с помощью основных конструкций, необходимых для структурной навигации. В этом разделе показано, как установить структурной навигации с помощью PageFunction<T>.
Структурная навигация
Когда одна страница вызывает другую в структурной навигации, необходимы некоторые или все из следующих видов поведения.
Переход выполняется с вызывающей страницы на вызываемую. При этом могут передаваться параметры, необходимые вызываемой странице.
Когда пользователь завершает работу с вызывающей страницей, вызванная страница может возвращать вызывающей странице следующее:
Возврат информации о состоянии, которая описывает, как была завершена работа с вызывающей страницей (например, пользователь нажал кнопку "ОК" или "Отмена").
Возврат данных, которые были получены от пользователя (например, сведения о новом сотруднике).
Когда вызывающая страница возвращается к вызываемой, вызванная страница удаляется из журнала навигации, чтобы изолировать один экземпляр вызываемой страницы от другого.
Эти виды поведения показаны на следующем рисунке:
Эти поведения можно реализовать с помощью PageFunction<T> качестве вызываемой страницы.
Структурная навигация с помощью PageFunction
В этом разделе показано, как реализовать основной механизм структурной навигации с одним PageFunction<T>. В этом образце Page вызовы PageFunction<T> для получения String от пользователя и вернуть его.
Создание вызывающей страницы
Страница, которая вызывает PageFunction<T> может быть либо Page или PageFunction<T>. В этом примере это Page, как показано в следующем коде.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="StructuredNavigationSample.CallingPage"
WindowTitle="Calling Page"
WindowWidth="250" WindowHeight="150">
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
}
}
}
Создание страничной функции для вызова
Поскольку вызывающая страница может использовать вызываемую страницу для сбора и возврата данных от пользователя, PageFunction<T> реализуется в виде универсального класса, тип аргумента которого определяет тип значения, возвращаемого вызываемой страницей. Следующий код показывает начальную реализацию вызываемой страницы, используя PageFunction<T>, который возвращает String.
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="StructuredNavigationSample.CalledPageFunction"
x:TypeArguments="sys:String"
Title="Page Function"
WindowWidth="250" WindowHeight="150">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Data -->
<Label Grid.Column="0" Grid.Row="0">DataItem1:</Label>
<TextBox Grid.Column="1" Grid.Row="0" Name="dataItem1TextBox"></TextBox>
<!-- Accept/Cancel buttons -->
<TextBlock Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right">
<Button Name="okButton" IsDefault="True" MinWidth="50">OK</Button>
<Button Name="cancelButton" IsCancel="True" MinWidth="50">Cancel</Button>
</TextBlock>
</Grid>
</PageFunction>
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
public CalledPageFunction()
{
InitializeComponent();
}
}
}
Объявление PageFunction<T> похоже на объявление Page с добавлением аргументов типа. Как видно из примера кода, аргументы типа указаны и в разметке XAML с помощью атрибута x:TypeArguments
, и в коде программной части с помощью стандартного синтаксиса аргумента универсального типа.
Не нужно использовать только классы .NET Framework в качестве аргументов типа. Объект PageFunction<T> может быть вызван для сбора данных отдельного домена, которые абстрагированы как пользовательский тип. Ниже показано, как использовать пользовательский тип в качестве аргумента типа для PageFunction<T>.
namespace SDKSample
{
public class CustomType
{
}
}
<PageFunction
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.CustomTypePageFunction"
x:TypeArguments="local:CustomType">
</PageFunction>
using System.Windows.Navigation;
namespace SDKSample
{
public partial class CustomTypePageFunction : PageFunction<CustomType>
{
}
}
Аргументы типа для PageFunction<T> обеспечивают основу для связи между вызывающей и вызываемой страницами, которые рассматриваются в следующих разделах.
Как вы увидите, тип, который идентифицируется с помощью объявления PageFunction<T> играет важную роль в возврате данных из PageFunction<T> вызывающей странице.
Вызов PageFunction и передача параметров
Чтобы вызвать страницу, вызывающая страница должна создать экземпляр вызываемой страницы и перейдите к нему с помощью Navigate метод. Это позволяет вызывающей странице передавать вызываемой начальные данные, например, значения по умолчанию для данных, собираемых вызываемой страницей.
В следующем коде показана вызываемая страница с нестандартным конструктором, который принимает параметры от вызывающей страницы.
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
public CalledPageFunction(string initialDataItem1Value)
{
InitializeComponent();
// Set initial value
this.dataItem1TextBox.Text = initialDataItem1Value;
}
}
}
В следующем коде показано вызывающая страница, обрабатывающая Click событие Hyperlink для создания экземпляра вызываемой страницы и передачи ей исходного строкового параметра.
<Hyperlink Name="pageFunctionHyperlink">Call Page Function</Hyperlink>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
this.pageFunctionHyperlink.Click += new RoutedEventHandler(pageFunctionHyperlink_Click);
}
void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
{
// Instantiate and navigate to page function
CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");
}
}
}
Необязательно передавать параметры вызываемой странице. Вместо этого можно сделать следующее.
Из вызывающей страницы:
Создать экземпляр вызываемой PageFunction<T> с помощью конструктора по умолчанию.
Параметры в Store Properties.
Перейдите к вызываемому PageFunction<T>.
Из вызванной PageFunction<T>:
- Получить и использовать параметры, сохраненные в Properties.
Однако вскоре вы увидите, что и в этом случае потребуется код для создания экземпляра и перехода к вызываемой странице для сбора данных, возвращаемых вызываемой страницей. По этой причине PageFunction<T> должен поддерживаться; в противном случае — значение, в следующий раз вы переходите PageFunction<T>, WPF создает PageFunction<T> с помощью конструктора по умолчанию.
Однако до возврата вызываемой страницы она должна вернуть данные, которые могут быть получены вызывающей страницей.
Возврат результата и данных задачи из задачи на вызывающую страницу
Когда пользователь закончит использовать вызываемую страницу (в данном примере он нажимает кнопку "ОК" или "Отмена"), необходим возврат вызываемой страницы. Поскольку вызывающая страница использовала вызываемую для сбора данных от пользователя, вызывающей странице необходимо два типа информации:
Отменил ли пользователь вызываемую страницу (нажав кнопку "ОК" или "Отмена" в этом примере). Это позволяет вызывающей странице определить, следует ли обрабатывать данные, собранные вызывающей страницей от пользователя.
Данные, предоставленные пользователем.
Для получения сведений, PageFunction<T> реализует OnReturn метод. В следующем коде показан его вызов.
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
void okButton_Click(object sender, RoutedEventArgs e)
{
// Accept when Ok button is clicked
OnReturn(new ReturnEventArgs<string>(this.dataItem1TextBox.Text));
}
void cancelButton_Click(object sender, RoutedEventArgs e)
{
// Cancel
OnReturn(null);
}
}
}
В этом примере, если пользователь нажимает кнопку "Отмена", значение null
возвращается вызывающей странице. Если нажата кнопка "ОК", возвращается строковый параметр, предоставленный пользователем. OnReturn является protected virtual
метод, который вы вызываете для возврата данных вызывающей странице. Данные необходимо упаковать в экземпляре универсального ReturnEventArgs<T> тип, тип аргумента которого определяет тип значения, Result возвращает. Таким образом, при объявлении PageFunction<T> с определенным аргументом типа, вы заявляете, что PageFunction<T> возвращает экземпляр типа, указанного аргументом типа. В этом примере аргумент типа и, следовательно, возвращаемое значение имеет тип String.
Когда OnReturn называется вызывающей странице требуется способ получения возвращаемого значения PageFunction<T>. По этой причине PageFunction<T> реализует Return событие для вызывающей страницы для обработки. При OnReturn вызове Return вызывается, поэтому вызывающая страница может зарегистрироваться с Return для получения уведомлений.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
{
// Instantiate and navigate to page function
CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");
CalledPageFunction.Return += pageFunction_Return;
this.NavigationService.Navigate(CalledPageFunction);
}
void pageFunction_Return(object sender, ReturnEventArgs<string> e)
{
this.pageFunctionResultsTextBlock.Visibility = Visibility.Visible;
// Display result
this.pageFunctionResultsTextBlock.Text = (e != null ? "Accepted" : "Canceled");
// If page function returned, display result and data
if (e != null)
{
this.pageFunctionResultsTextBlock.Text += "\n" + e.Result;
}
}
}
}
Удаление страниц задачи после завершения задачи
Когда вызываемая страница возвращается и пользователь не отменяет ее, вызывающая страница будет обрабатывать данные, предоставленные пользователем и возвращенные вызываемой страницей. Сбор данных таким способом, как правило, является изолированным действием. Когда возвращается вызываемая страница, вызывающей странице необходимо создать новую вызывающую страницу и перейти к ней для сбора дополнительных данных.
Однако, если вызываемая страница не удалена из журнала, пользователь сможет перейти обратно к предыдущему экземпляру вызывающей страницы. Ли PageFunction<T> сохраняется в журнале, определяется RemoveFromJournal свойство. По умолчанию — страничная функция автоматически удаляется, когда OnReturn называется, поскольку RemoveFromJournal присваивается true
. Чтобы сохранить страничную функцию в журнале навигации после OnReturn вызывается, задайте RemoveFromJournal для false
.
Другие типы структурной навигации
В этом разделе показан самый простой метод PageFunction<T> для поддержки вызова/возврата структурной навигации. На этой основе можно создавать более сложные типы структурной навигации.
Например, иногда вызывающей странице требуется несколько страниц для сбора достаточного количества данных от пользователя или выполнения задачи. Использование нескольких страниц называется "мастер".
В других случаях для эффективной работы приложения могут иметь сложные топологии переходов, зависящие от структурной навигации. Дополнительную информацию см. в разделе Общие сведения о топологиях навигации.