結構化巡覽概觀
XAML browser application (XBAP)、Frame 或 NavigationWindow 可裝載的內容是由頁面所組成,這些頁面可由套件的 uniform resource identifiers (URIs) 識別,而且可使用超連結巡覽。 頁面的結構和巡覽頁面的方式 (如超連結所定義) 稱為巡覽拓撲。 這種拓撲適合各種應用程式類型,特別是巡覽文件的應用程式。 針對這類應用程式,使用者可以從一頁巡覽到另一頁,而各頁面無須知道彼此的內容。
不過,其他應用程式類型的頁面則需要知道有巡覽關係的頁面。 例如,假設人力資源應用程式有一頁列出組織中的所有員工,這頁稱為「列出員工」頁面。 此頁也可讓使用者按一下超連結來加入新員工。 按下超連結時,頁面會巡覽至「加入員工」頁面以收集新員工的詳細資料,然後將這些資料傳回「列出員工」頁面,以建立新員工並更新清單。 這種巡覽方式類似於呼叫方法來進行處理並傳回值的結構化程式設計。 因此,這種巡覽方式就稱為「結構化巡覽」(Structured Navigation)。
Page 類別不會實作結構化巡覽的支援。 相反地,PageFunction<T> 類別會衍生自 Page,並擴充加入結構化巡覽所需的基本建構。 本主題顯示如何使用 PageFunction<T> 建立結構化巡覽。
這個主題包含下列章節。
- 結構化巡覽
- 使用 PageFunction 進行結構化巡覽
- 其他結構化巡覽類型
- 相關主題
結構化巡覽
當某個頁面呼叫結構化巡覽中的另一頁面時,需要下列部分或所有行為:
呼叫頁面會巡覽至被呼叫頁面,並選擇性傳遞被呼叫頁面所需的參數。
當使用者使用完呼叫頁面後,被呼叫頁面會特別回到呼叫頁面,並選擇性:
傳回描述呼叫頁面如何完成的狀態資訊 (例如,使用者是按 [確定] 按鈕或 [取消] 按鈕)。
傳回使用者所提供的資料 (例如新員工的詳細資料)。
當呼叫頁面回到被呼叫頁面時,被呼叫頁面會從巡覽記錄移除,以將被呼叫頁面的執行個體隔離開來。
下圖說明這些行為。
您可以使用 PageFunction<T> 當做被呼叫頁面,以實作這些行為。
使用 PageFunction 進行結構化巡覽
本主題顯示如何實作使用單一 PageFunction<T> 的結構化巡覽基本機制。 在這個範例中,Page 會呼叫 PageFunction<T> 以取得使用者提供的 String 並傳回它。
建立呼叫頁面
呼叫 PageFunction<T> 的頁面可以是 Page 或 PageFunction<T>。 在這個範例中,這是 Page,如下列程式碼所示。
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="StructuredNavigationSample.CallingPage"
WindowTitle="Calling Page"
WindowWidth="250" WindowHeight="150">
...
</Page>
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
Public Sub New()
Me.InitializeComponent()
...
End Sub
...
End Class
End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
...
}
...
}
}
建立頁面函式進行呼叫
由於呼叫頁面可使用被呼叫頁面收集和傳回使用者提供的資料,因此 PageFunction<T> 會實作為泛型類別,其型別引數會指定被呼叫頁面傳回值的型別。 下列程式碼顯示被呼叫頁面的初始實作,其使用傳回 String 的 PageFunction<T>。
<PageFunction
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://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>
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
Public Sub New()
Me.InitializeComponent()
End Sub
...
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
public CalledPageFunction()
{
InitializeComponent();
}
...
}
}
PageFunction<T> 的宣告和 Page 宣告類似,不過還加入了型別引數。 如程式碼範例所示,型別引數同時在 XAML 標記 (使用 x:TypeArguments 屬性) 和程式碼後置 (使用標準泛型型別引數語法) 中指定。
不一定只有 .NET Framework 類別才能當做型別引數。 您可以呼叫 PageFunction<T> 收集提取為自訂型別的定義域特定資料。 下列程式碼顯示如何使用自訂型別做為 PageFunction<T> 的型別引數。
Public Class CustomType
...
End Class
namespace SDKSample
{
public class CustomType
{
...
}
}
<PageFunction
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.CustomTypePageFunction"
x:TypeArguments="local:CustomType">
...
</PageFunction>
Partial Public Class CustomTypePageFunction
Inherits System.Windows.Navigation.PageFunction(Of CustomType)
using System.Windows.Navigation; // PageFunction
namespace SDKSample
{
public partial class CustomTypePageFunction : PageFunction<CustomType>
{
PageFunction<T> 的型別引數提供呼叫頁面與被呼叫頁面之間的通訊基礎,這將在下列章節討論。
您將會了解,使用 PageFunction<T> 宣告所識別的型別,在將資料從 PageFunction<T> 傳回到呼叫頁面上,扮演了重要角色。
呼叫 PageFunction 和傳遞參數
若要呼叫頁面,呼叫頁面必須將被呼叫頁面執行個體化,並使用 Navigate 方法巡覽至該頁面。 這可讓呼叫頁面將初始資料傳遞至被呼叫頁面,例如要讓被呼叫頁面收集之資料的預設值。
下列程式碼顯示所呼叫的頁面,它使用非預設建構函式接受來自呼叫頁面的參數。
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
Public Sub New(ByVal initialDataItem1Value As String)
Me.InitializeComponent()
...
' Set initial value
Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub
...
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
...
public CalledPageFunction(string initialDataItem1Value)
{
InitializeComponent();
...
// Set initial value
this.dataItem1TextBox.Text = initialDataItem1Value;
}
...
}
}
下列程式碼顯示呼叫頁面處理 Click (將被呼叫頁面執行個體化並傳遞初始字串值給它) 的 Hyperlink 事件。
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs
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
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs
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");
...
}
...
}
}
<Hyperlink Name="pageFunctionHyperlink">Call Page Function</Hyperlink>
您不需要傳遞參數給被呼叫頁面。 您可以改執行以下動作:
從呼叫頁面:
使用預設建構函式將被呼叫的 PageFunction<T> 執行個體化。
將參數儲存在 Properties。
巡覽至被呼叫的 PageFunction<T>。
從被呼叫的 PageFunction<T>:
- 擷取並使用儲存在 Properties 的參數。
但是,如稍後所見,您還是需要使用程式碼將被呼叫頁面執行個體化並巡覽至該頁面,才能收集被呼叫頁面傳回的資料。 因此,PageFunction<T> 需要保持運作,否則下次巡覽至 PageFunction<T> 時,WPF 會使用預設建構函式將 PageFunction<T> 執行個體化。
不過,在被呼叫頁面返回之前,它需要傳回可由呼叫頁面擷取的資料。
傳回工作的工作結果和工作資料給呼叫頁面
一旦使用者使用完被呼叫頁面 (此範例是按下 [確定] 或 [取消] 按鈕來表示),被呼叫頁面就需要返回。 由於呼叫頁面是使用被呼叫頁面收集使用者提供的資料,因此呼叫頁面需要兩種類型的資訊:
使用者是否取消了被呼叫頁面 (此範例是藉由按下 [確定] 或 [取消] 按鈕)。 這可讓呼叫頁面判斷是否要處理呼叫頁面從使用者收集到的資料。
使用者所提供的資料。
為傳回資訊,PageFunction<T> 會實作 OnReturn 方法。 下列程式碼顯示如何呼叫它。
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
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
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
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 註冊來接收通知。
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
...
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
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs
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> 用法,以支援呼叫/返回結構化巡覽。 您可以此為基礎,建立更複雜的結構化巡覽類型。
例如,呼叫頁面可能需要多個頁面才能向使用者收集足夠的資料或執行工作。 多個頁面的用法稱為「精靈」。
在其他情況下,應用程式可能有複雜的巡覽拓撲,需要依賴結構化巡覽才能有效運作。 如需詳細資訊,請參閱 巡覽拓撲概觀。