Udostępnij za pośrednictwem


Omówienie nawigacji strukturalnej

Zawartość, którą może hostować aplikacja przeglądarki XAML (XBAP), Framelub NavigationWindow, składa się z stron, które mogą być identyfikowane za pomocą identyfikatorów URI pakietu i do których można nawigować za pomocą hiperlinków. Struktura stron i sposobów nawigowania, zgodnie z definicją hiperlinków, jest nazywana topologią nawigacji. Taka topologia pasuje do różnych typów aplikacji, szczególnie tych, które przechodzą przez dokumenty. W przypadku takich aplikacji użytkownik może przechodzić z jednej strony do innej bez konieczności znajomości żadnej ze stron.

Jednak inne typy aplikacji mają strony, które muszą wiedzieć, kiedy się między nimi przechodzi. Rozważmy na przykład aplikację kadr, która ma jedną stronę, aby wyświetlić listę wszystkich pracowników w organizacji — stronę "Lista pracowników". Ta strona może również umożliwić użytkownikom dodawanie nowego pracownika, klikając hiperlink. Po kliknięciu strona przechodzi do strony "Dodaj pracownika", aby zebrać szczegóły nowego pracownika i zwrócić je do strony "Lista pracowników", aby utworzyć nowego pracownika i zaktualizować listę. Ten styl nawigacji jest podobny do wywoływania metody w celu wykonania pewnego przetwarzania i zwrócenia wartości, która jest znana jako programowanie strukturalne. W związku z tym ten styl nawigacji jest znany jako nawigacja ze strukturą .

Klasa Page nie implementuje obsługi nawigacji strukturalnej. Zamiast tego klasa PageFunction<T> pochodzi z Page i rozszerza ją o podstawowe konstrukcje wymagane do nawigacji strukturalnej. W tym temacie pokazano, jak ustanowić ustrukturyzowaną nawigację przy użyciu PageFunction<T>.

Nawigacja ze strukturą

Gdy jedna strona wywołuje inną stronę w nawigacji ze strukturą, wymagane są niektóre lub wszystkie następujące zachowania:

  • Strona wywołująca przechodzi do wywoływanej strony, opcjonalnie przekazując parametry wymagane przez wywołaną stronę.

  • Wywołana strona, po zakończeniu korzystania ze strony wywołującej przez użytkownika, zostaje opcjonalnie przekierowana z powrotem na stronę wywołującą.

    • Zwracanie informacji o stanie opisujących sposób ukończenia strony wywołującej (na przykład tego, czy użytkownik nacisnął przycisk OK, czy przycisk Anuluj).

    • Zwracanie tych danych zebranych od użytkownika (na przykład nowych szczegółów pracownika).

  • Gdy strona wywołująca powróci do wywoływanej strony, wywołana strona zostanie usunięta z historii nawigacji, aby odizolować jedno wystąpienie wywoływanej strony od innej.

Te zachowania przedstawiono na poniższej ilustracji:

Zrzut ekranu przedstawia przepływ między stroną wywołującą i wywołaną stroną.

Te zachowania można zaimplementować przy użyciu PageFunction<T> jako wywoływanej strony.

Strukturalna nawigacja z funkcją PageFunction

W tym temacie pokazano, w jaki sposób zaimplementować podstawową mechanikę nawigacji strukturalnej obejmującej jeden PageFunction<T>. W tym przykładzie Page wywołuje PageFunction<T>, aby uzyskać od użytkownika wartość String i ją zwrócić.

Tworzenie strony do nawiązywania połączeń

Strona wywołująca PageFunction<T> może być Page lub PageFunction<T>. W tym przykładzie jest to Page, jak pokazano w poniższym kodzie.

<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

Tworzenie funkcji strony do wywołania

Ponieważ strona wywołująca może używać wywoływanej strony do zbierania i zwracania danych od użytkownika, PageFunction<T> jest implementowana jako klasa ogólna, której argument typu określa typ wartości zwracanej przez wywołaną stronę. Poniższy kod przedstawia początkową implementację wywoływanej strony przy użyciu PageFunction<T>, która zwraca 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

Deklaracja PageFunction<T> jest podobna do deklaracji Page z dodawaniem argumentów typu. Jak widać w przykładzie kodu, argumenty typu są określone zarówno w znaczniku XAML, przy użyciu atrybutu x:TypeArguments, jak i w kodzie za pomocą standardowej składni argumentu typu ogólnego.

Nie musisz używać tylko klas programu .NET Framework jako argumentów typu. Można wywołać PageFunction<T>, aby zebrać dane charakterystyczne dla danej domeny, które są przedstawiane jako typ niestandardowy. Poniższy kod pokazuje, jak używać typu niestandardowego jako argumentu typu dla 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

Argumenty typu dla PageFunction<T> stanowią podstawę komunikacji między stroną wywołującą a wywołaną stroną, które zostały omówione w poniższych sekcjach.

Jak zobaczysz, typ, który jest identyfikowany za pomocą deklaracji PageFunction<T>, odgrywa istotną rolę w zwracaniu danych z PageFunction<T> na stronę wywołującą.

Wywoływanie PageFunction i przekazywanie parametrów

Aby wywołać stronę, strona wywołująca musi utworzyć instancję strony, którą chce wywołać, i przejść do niej za pomocą metody Navigate. Dzięki temu strona wywołująca może przekazywać początkowe dane do wywoływanej strony, na przykład wartości domyślne dla danych zbieranych przez wywołaną stronę.

Poniższy kod przedstawia wywołaną stronę z konstruktorem bez parametrów umożliwiającym akceptowanie parametrów ze strony wywołującej.

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

Poniższy kod pokazuje, jak strona wywołująca obsługuje zdarzenie Click obiektu Hyperlink, aby utworzyć instancję wywołanej strony i przekazać jej wstępną wartość tekstową.

<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

Nie musisz przekazywać parametrów do wywoływanej strony. Zamiast tego można wykonać następujące czynności:

Jednak jak zobaczysz wkrótce, nadal będziesz potrzebować kodu, aby utworzyć wystąpienie i przejść do wywoływanej strony, aby zebrać dane zwrócone przez wywołaną stronę. Z tego powodu PageFunction<T> muszą być utrzymywane przy życiu; w przeciwnym razie przy następnej nawigacji do PageFunction<T>WPF tworzy wystąpienie PageFunction<T> przy użyciu konstruktora bez parametrów.

Zanim jednak strona wywołana będzie mogła się zamknąć, musi zwrócić dane, które można pobrać przez stronę wywołującą.

Zwracanie wyników i danych z zadania do strony wywołującej

Gdy użytkownik zakończy korzystanie z wywoływanej strony, co w tym przykładzie następuje po naciśnięciu przycisków OK lub Anuluj, wywoływana strona musi się zamknąć i powrócić do poprzedniego widoku. Ponieważ strona wywołująca użyła wywoływanej strony do zbierania danych od użytkownika, strona wywołująca wymaga dwóch typów informacji:

  1. Czy użytkownik anulował wywołaną stronę (naciskając przycisk OK lub przycisk Anuluj w tym przykładzie). Dzięki temu strona wywołująca może określić, czy przetwarzać dane zebrane od użytkownika.

  2. Dane, które zostały dostarczone przez użytkownika.

Aby zwrócić informacje, PageFunction<T> implementuje metodę OnReturn. Poniższy kod pokazuje, jak go wywołać.

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

W tym przykładzie, jeśli użytkownik naciśnie przycisk Anuluj, do strony wywołującej zostanie zwrócona wartość null. Jeśli zamiast tego zostanie naciśnięty przycisk OK, zostanie zwrócona wartość ciągu podana przez użytkownika. OnReturn to metoda protected virtual, którą wywołujesz w celu zwrócenia danych do strony wywołującej. Dane muszą być spakowane w wystąpieniu ogólnego typu ReturnEventArgs<T>, którego argument type określa typ wartości zwracanej przez Result. W ten sposób podczas deklarowania PageFunction<T> za pomocą określonego argumentu typu stwierdza się, że PageFunction<T> zwróci wystąpienie typu określonego przez argument typu. W tym przykładzie argument typu i w związku z tym zwracana wartość jest typu String.

Kiedy funkcja OnReturn jest wywoływana, strona wywołująca potrzebuje sposobu na odebranie wartości zwracanej przez PageFunction<T>. Z tego powodu PageFunction<T> implementuje zdarzenie Return w celu obsługi stron wywołujących. Po wywołaniu OnReturn zostanie uruchomione Return, aby strona wywołująca mogła zarejestrować się przy użyciu Return, aby odebrać powiadomienie.

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

Usuwanie stron zadań po zakończeniu zadania

Gdy wywołana strona zostanie zwrócona, a użytkownik nie anulował wywoływanej strony, strona wywołująca będzie przetwarzać dane dostarczone przez użytkownika, a także zwracane ze strony wywoływanej. Pozyskiwanie danych w ten sposób jest zwykle działaniem izolowanym; gdy wywołana strona wraca, strona wywołująca musi utworzyć nową stronę i przejść do niej, aby przechwycić więcej danych.

Jeśli jednak wywołana strona nie zostanie usunięta z dziennika, użytkownik będzie mógł wrócić do poprzedniego wystąpienia strony wywołującej. Czy PageFunction<T> jest zachowywana w dzienniku, jest określana przez właściwość RemoveFromJournal. Domyślnie funkcja strony jest automatycznie usuwana po wywołaniu OnReturn, ponieważ RemoveFromJournal jest ustawiona na wartość true. Aby zachować funkcję strony w historii nawigacji po wywołaniu OnReturn, ustaw RemoveFromJournal na false.

Inne typy nawigacji strukturalnej

W tym temacie przedstawiono najbardziej podstawowe użycie PageFunction<T> do obsługi nawigacji ze strukturą wywołania/powrotu. Ta podstawa zapewnia możliwość tworzenia bardziej złożonych typów nawigacji strukturalnej.

Na przykład czasami wiele stron jest wymaganych przez stronę wywołującą w celu zebrania wystarczającej ilości danych od użytkownika lub wykonania zadania. Użycie wielu stron jest określane jako "asystent".

W innych przypadkach aplikacje mogą mieć złożone topologie nawigacji, które zależą od nawigacji strukturalnej w celu efektywnego działania. Aby uzyskać więcej informacji, zobacz Omówienie topologii nawigacji.

Zobacz też