構造化ナビゲーションの概要
XAML ブラウザー アプリケーション (XBAP)、Frame、または NavigationWindow でホストできるコンテンツは、パックの UNIFORM リソース識別子 (URI) で識別し、ハイパーリンクで移動できるページで構成されます。 ページの構造と、ハイパーリンクで定義されているページの移動方法は、ナビゲーション トポロジと呼ばれます。 このようなトポロジは、さまざまな種類のアプリケーション 、特にドキュメント内を移動するアプリケーションに適しています。 このようなアプリケーションの場合、ユーザーは、いずれかのページが他のページについて何も知る必要なく、1 つのページから別のページに移動できます。
ただし、他の種類のアプリケーションでは、ページ間を移動したことを認識する必要があるページがあります。 たとえば、組織内のすべての従業員を一覧表示する 1 つのページ ([従業員の一覧表示] ページ) がある人事アプリケーションを考えてみましょう。 このページでは、ユーザーがハイパーリンクをクリックして新しい従業員を追加することもできます。 クリックすると、新しい従業員の詳細を収集する [従業員の追加] ページに移動し、[従業員の一覧] ページに戻って新しい従業員を作成し、リストを更新します。 このスタイルのナビゲーションは、メソッドを呼び出して何らかの処理を実行し、値を返すことと似ています。これは構造化プログラミングと呼ばれます。 そのため、このスタイルのナビゲーションは、構造化ナビゲーションと呼ばれます。
Page クラスは、構造化ナビゲーションのサポートを実装していません。 代わりに、PageFunction<T> クラスは Page から派生し、構造化ナビゲーションに必要な基本的なコンストラクトで拡張します。 このトピックでは、PageFunction<T>を使用して構造化ナビゲーションを確立する方法について説明します。
構造化ナビゲーション
あるページが構造化ナビゲーションで別のページを呼び出す場合、次の動作の一部またはすべてが必要です。
呼び出し元のページは呼び出されたページに移動し、必要に応じて呼び出されたページに必要なパラメーターを渡します。
呼び出されたページは、ユーザーが呼び出し元ページの使用を終了した後、必要に応じてそのページに戻ることができます。
呼び出し元ページの完了方法を説明する状態情報を返します (たとえば、ユーザーが [OK] ボタンまたは [キャンセル] ボタンを押したかどうか)。
ユーザーから収集されたデータを返す (たとえば、新しい従業員の詳細)。
呼び出し元のページが呼び出し元のページに戻ると、呼び出されたページがナビゲーション履歴から削除され、呼び出されたページのインスタンスが別のページから分離されます。
これらの動作を次の図に示します。
これらの動作は、呼び出されたページとして PageFunction<T> を使用して実装できます。
PageFunction を使用した構造化ナビゲーション
このトピックでは、1 つの 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();
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
Public Sub New()
Me.InitializeComponent()
}
End Sub
}
}
End Class
End Namespace
呼び出すページ関数の作成
呼び出し元のページは呼び出し元のページを使用してユーザーからデータを収集して返すことができるため、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();
}
Imports System.Windows
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
Public Sub New()
Me.InitializeComponent()
End Sub
}
}
End Class
End Namespace
PageFunction<T> の宣言は、型引数を追加した Page の宣言に似ています。 コード例からわかるように、型引数は XAML マークアップでは x:TypeArguments
属性を使用して、コードビハインドでは標準のジェネリック型引数構文を使用して、それぞれ指定されます。
型引数として .NET Framework クラスのみを使用する必要はありません。 PageFunction<T> を呼び出して、カスタム型として抽象化されたドメイン固有のデータを収集できます。 次のコードは、PageFunction<T>の型引数としてカスタム型を使用する方法を示しています。
namespace SDKSample
{
public class CustomType
{
Public Class CustomType
}
}
End Class
<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>
{
Partial Public Class CustomTypePageFunction
Inherits System.Windows.Navigation.PageFunction(Of CustomType)
}
}
End Class
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>
{
Imports System.Windows
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
public CalledPageFunction(string initialDataItem1Value)
{
InitializeComponent();
Public Sub New(ByVal initialDataItem1Value As String)
Me.InitializeComponent()
// Set initial value
this.dataItem1TextBox.Text = initialDataItem1Value;
}
' Set initial value
Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub
}
}
End Class
End Namespace
次のコードは、呼び出されたページをインスタンス化して初期文字列値を渡す Hyperlink の Click イベントを処理する呼び出し元のページを示しています。
<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");
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
Public Sub New()
Me.InitializeComponent()
AddHandler Me.pageFunctionHyperlink.Click, New RoutedEventHandler(AddressOf Me.pageFunctionHyperlink_Click)
End Sub
Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
}
End Sub
}
}
End Class
End Namespace
呼び出されたページにパラメーターを渡す必要はありません。 代わりに、次の操作を行うことができます。
呼び出し元のページから:
パラメーターなしのコンストラクターを使用して、呼び出された PageFunction<T> をインスタンス化します。
パラメーターを Propertiesに格納します。
呼び出された PageFunction<T>に移動します。
呼び出された PageFunction<T>から:
- Propertiesに格納されているパラメーターを取得して使用します。
ただし、すぐにわかるように、呼び出されたページから返されたデータを収集するには、呼び出されたページをインスタンス化して移動するコードを使用する必要があります。 このため、PageFunction<T> を維持する必要があります。それ以外の場合、次に PageFunction<T>に移動すると、WPF はパラメーターなしのコンストラクターを使用して PageFunction<T> をインスタンス化します。
ただし、呼び出されたページが返される前に、呼び出し元のページで取得できるデータを返す必要があります。
タスクから呼び出し元ページにタスクの結果とタスク データを返す
ユーザーが呼び出されたページの使用を完了したら、この例で示されている [OK] または [キャンセル] ボタンを押すと、呼び出されたページが返される必要があります。 呼び出し元ページは呼び出し元のページを使用してユーザーからデータを収集するため、呼び出し元のページには次の 2 種類の情報が必要です。
ユーザーが呼び出されたページをキャンセルしたかどうか (この例では[OK] ボタンまたは [キャンセル] ボタンを押します)。 これにより、呼び出し元ページは、呼び出し元のページがユーザーから収集したデータを処理するかどうかを決定できます。
ユーザーによって提供されたデータ。
情報を返すために、PageFunction<T> は OnReturn メソッドを実装します。 次のコードは、それを呼び出す方法を示しています。
using System;
using System.Windows;
using System.Windows.Navigation;
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
Imports System.Windows
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of 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);
}
}
}
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Accept when Ok button is clicked
Me.OnReturn(New ReturnEventArgs(Of String)(Me.dataItem1TextBox.Text))
End Sub
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Cancel
Me.OnReturn(Nothing)
End Sub
End Class
End Namespace
この例では、ユーザーが [キャンセル] ボタンを押すと、null
の値が呼び出し元のページに返されます。 代わりに [OK] ボタンを押すと、ユーザーが指定した文字列値が返されます。 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
{
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits 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;
}
}
}
}
Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Instantiate and navigate to page function
Dim calledPageFunction As New CalledPageFunction("Initial Data Item Value")
AddHandler calledPageFunction.Return, New ReturnEventHandler(Of String)(AddressOf Me.calledPageFunction_Return)
MyBase.NavigationService.Navigate(calledPageFunction)
End Sub
Private Sub calledPageFunction_Return(ByVal sender As Object, ByVal e As ReturnEventArgs(Of String))
Me.pageFunctionResultsTextBlock.Visibility = Windows.Visibility.Visible
' Display result
Me.pageFunctionResultsTextBlock.Text = IIf((Not e Is Nothing), "Accepted", "Canceled")
' If page function returned, display result and data
If (Not e Is Nothing) Then
Me.pageFunctionResultsTextBlock.Text = (Me.pageFunctionResultsTextBlock.Text & ChrW(10) & e.Result)
End If
End Sub
End Class
End Namespace
タスクが完了したときのタスク ページの削除
呼び出されたページが返され、ユーザーが呼び出されたページを取り消さなかった場合、呼び出し元のページは、ユーザーによって提供され、呼び出されたページからも返されたデータを処理します。 この方法でのデータの取得は、通常、分離されたアクティビティです。呼び出されたページが返されたら、呼び出し元のページを作成し、新しい呼び出し元ページに移動して、より多くのデータをキャプチャする必要があります。
ただし、呼び出されたページがジャーナルから削除されない限り、ユーザーは呼び出し元ページの前のインスタンスに戻ります。 PageFunction<T> が履歴に保持されるかどうかは、RemoveFromJournal プロパティによって決まります。 既定では、RemoveFromJournal が true
に設定されているため、OnReturn が呼び出されると、ページ関数は自動的に削除されます。 OnReturn が呼び出された後もページ関数をナビゲーション履歴に保持するには、RemoveFromJournal を false
に設定します。
その他の種類の構造化ナビゲーション
このトピックでは、呼び出し/戻り構造化ナビゲーションをサポートする PageFunction<T> の最も基本的な使用方法について説明します。 この基盤では、より複雑な種類の構造化ナビゲーションを作成できます。
たとえば、ユーザーから十分なデータを収集したり、タスクを実行したりするために、呼び出し元のページで複数のページが必要になる場合があります。 複数のページの使用は、"ウィザード" と呼ばれます。
また、アプリケーションには、効果的に動作するための構造化ナビゲーションに依存する複雑なナビゲーション トポロジが存在する場合があります。 詳細については、「ナビゲーション トポロジの概要」を参照してください。
関連項目
.NET Desktop feedback