Übersicht über die Navigation

Windows Presentation Foundation (WPF) unterstützt die Navigation im Browserstil, die in zwei Arten von Anwendungen verwendet werden kann: eigenständigen Anwendungen und XAML-Browseranwendungen (XBAPs). Zum Verpacken von Inhalten für die Navigation stellt WPF die Page-Klasse zur Verfügung. Sie können von einer Page zu einer anderen deklarativ, durch Verwenden eines Hyperlink oder programmgesteuert mithilfe des NavigationService navigieren. WPF verwendet das Journal, um Seiten zu speichern, von denen weg navigiert wurde, und um wieder zu den Seiten zurück zu navigieren.

Page, Hyperlink, NavigationService und das Journal bilden den Kern der Navigationsunterstützung, die von WPF zur Verfügung gestellt wird. In dieser Übersicht werden diese Features ausführlich untersucht, bevor die erweiterte Navigationsunterstützung behandelt wird, die die Navigation zu Loose XAML-Dateien (Extensible Application Markup Language), HTML-Dateien und Objekten beinhaltet.

Hinweis

In diesem Thema bezieht sich der Begriff „Browser“ lediglich auf Browser, die WPF-Anwendungen hosten können. Gegenwärtig zählen Microsoft Internet Explorer und Firefox zu diesen Browsern. Die Browserversion wird angegeben, wenn spezielle WPF-Features nur von einem bestimmten Browser unterstützt werden.

In diesem Thema erhalten Sie eine Übersicht zu den entscheidenden Navigationsfunktionen in WPF. Diese Funktionen sind sowohl für eigenständige Anwendungen als auch für XBAPs verfügbar, auch wenn sie in diesem Thema im Kontext einer XBAP vorgestellt werden.

Hinweis

In diesem Thema wird das Erstellen und Bereitstellen von XBAPs nicht erläutert. Weitere Informationen zu XBAPs finden Sie unter Übersicht über WPF-XAML-Browseranwendungen.

In diesem Abschnitt werden die folgenden Aspekte der Navigation erklärt und veranschaulicht:

Implementieren einer Seite

In WPF können Sie zu verschiedenen Inhaltstypen navigieren, die .NET Framework-Objekte, benutzerdefinierte Objekte, Enumerationswerte, Benutzersteuerelemente, XAML-Dateien und -HTML-Dateien umfassen. Sie werden jedoch feststellen, dass die Verwendung von Page die gebräuchlichste und bequemste Methode zum Packen von Inhalt ist. Außerdem implementiert Page navigationsspezifische Funktionen, um die Darstellung zu verbessern und die Entwicklung zu vereinfachen.

Die Verwendung von Page ermöglicht Ihnen das deklarative Implementieren einer navigierbaren Seite von XAML-Inhalt, indem Sie Markup wie das folgende verwenden.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />

Eine in XAML-Markup implementierte Page weist Page als Stammelement auf und erfordert die WPF XML-Namespacedeklaration. Das Page-Element enthält den Inhalt, zu dem Sie navigieren und den Sie anzeigen möchten. Sie fügen Inhalt hinzu, indem Sie das Page.Content-Eigenschaftenelement festlegen, wie im folgenden Markup gezeigt.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Page.Content>
    <!-- Page Content -->
    Hello, Page!
  </Page.Content>
</Page>

Page.Content kann nur ein untergeordnetes Element enthalten; im vorstehenden Beispiel ist der Inhalt eine einzelne Zeichenfolge: „Hello, Page!“ In der Praxis verwenden Sie in der Regel ein Layoutsteuerelement als untergeordnetes Element (siehe Layout), um Ihre Inhalte zu beinhalten und zu verfassen.

Die untergeordneten Elemente eines Page-Elements gelten als Inhalte einer Page. Folglich brauchen Sie die explizite Page.Content-Deklaration nicht zu verwenden. Das folgende Markup stellt die deklarative Entsprechung zum vorherigen Beispiel dar.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <!-- Page Content -->
  Hello, Page!
</Page>

In diesem Fall wird Page.Content automatisch mit den untergeordneten Elementen des Page-Elements festgelegt. Weitere Informationen finden Sie unter WPF-Inhaltsmodell.

Eine nur aus Markup bestehende Page ist nützlich für das Anzeigen von Inhalten. Allerdings kann eine Page auch Steuerelemente anzeigen, mit deren Hilfe Benutzer mit der Seite interagieren. Außerdem kann sie auf Benutzerinteraktionen reagieren, indem Ereignisse behandelt und Anwendungslogik aufgerufen wird. Eine interaktive Page wird durch eine Kombination aus Markup und CodeBehind implementiert, wie im folgenden Beispiel dargestellt.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage">
  Hello, from the XBAP HomePage!
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }
    }
}

Imports System.Windows.Controls

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

Damit eine Markup- und eine Code-Behind-Datei zusammenarbeiten können, ist die folgende Konfiguration erforderlich:

  • Im Markup muss das Page-Element das x:Class-Attribut enthalten. Beim Erstellen der Anwendung führt das Vorhandensein von x:Class in der Markupdatei, die von einer Microsoft Build Engine (MSBuild) erstellt wird, dazu, dass eine partial-Klasse erstellt wird, die von Page abgeleitet wird und den durch das x:Class-Attribut festgelegten Namen erhält. Dies erfordert das Hinzufügen einer XML-Namespacedeklaration für das XAML-Schema (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"). Die erzeugte partial-Klasse implementiert InitializeComponent, das zum Registrieren der Ereignisse und Festlegen der im Markup implementierten Eigenschaften aufgerufen wird.

  • Bei Code-Behind muss die Klasse eine partial-Klasse mit demselben Namen sein, der im Markup durch das x:Classs-Attribut angegeben ist, und sie muss von Page abgeleitet werden. Auf diese Weise kann die CodeBehind-Datei mit der partial-Klasse verknüpft werden, die beim Erstellen der Anwendung (siehe Erstellen einer WPF-Anwendung) für die Markupdatei generiert wird.

  • Bei Code-Behind muss die Page-Klasse einen Konstruktor implementieren, der die InitializeComponent-Methode aufruft. InitializeComponent wird durch die generierte partial-Klasse der Markupdatei implementiert, um Ereignisse zu registrieren und im Markup definierte Eigenschaften festzulegen.

Hinweis

Wenn Sie Ihrem Projekt eine neue Page mithilfe von Visual Studio hinzufügen, wird die Page unter Verwendung von Markup und CodeBehind implementiert. Außerdem wird eine Konfiguration eingefügt, die zum Erstellen der Verknüpfung zwischen Markup- und CodeBehind-Dateien, wie hier beschrieben, benötigt wird.

Sobald Sie über eine Page verfügen, können Sie zu ihr navigieren. Zum Angeben der ersten Page, zu der eine Anwendung navigiert, müssen Sie die Start-Page konfigurieren.

Konfigurieren einer Startseite

XBAPs erfordern einen gewissen Umfang an Anwendungsinfrastruktur, um in einem Browser gehostet zu werden. In WPF ist die Application-Klasse Teil einer Anwendungsdefinition, die die erforderliche Anwendungsinfrastruktur (siehe Übersicht über die Anwendungsverwaltung) festlegt.

Eine Anwendungsdefinition wird normalerweise mithilfe von Markup und CodeBehind implementiert. Dabei wird die Markupdatei als ein MSBuild-ApplicationDefinition-Element konfiguriert. Das folgende Beispiel ist eine Anwendungsdefinition für eine XBAP.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application { }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
    End Class
End Namespace

Eine XBAP kann ihre Anwendungsdefinition nutzen, um eine Start-Page anzugeben. Dies ist die Page, die beim Starten der XBAP automatisch geladen wird. Dazu legen Sie die StartupUri-Eigenschaft mit dem URI (Uniform Resource Identifier) für die gewünschte Page fest.

Hinweis

In den meisten Fällen wird die Page entweder in eine Anwendung kompiliert oder mit einer Anwendung bereitgestellt. In diesen Fällen ist der URI, der eine Page identifiziert, ein Paket-URI, also ein URI, der dem Paketschema entspricht. Paket-URIs werden unter Paket-URIs in WPF ausführlicher erläutert. Sie können auch mit dem HTTP-Schema zum Inhalt navigieren. Das Schema wird nachfolgend erklärt.

Sie können StartupUri deklarativ in Markup festlegen, wie im folgenden Beispiel gezeigt.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="PageWithHyperlink.xaml" />

In diesem Beispiel wird das StartupUri-Attribut mit einem relativen Paket-URI festgelegt, der HomePage.xaml identifiziert. Wenn die XBAP gestartet wird, erfolgt automatisch die Navigation zu HomePage.xaml, die dann angezeigt wird. Dies wird in der folgenden Abbildung veranschaulicht, in der eine XBAP gezeigt wird, die von einem Webserver gestartet wurde.

XBAP-Seite

Hinweis

Weitere Informationen zu Entwicklung und Bereitstellung von XBAPs finden Sie in Übersicht über WPF-XAML-Browseranwendungen und in Bereitstellen von WPF-Anwendungen.

Konfigurieren von Titel, Breite und Höhe des Hostfensters

In der vorherigen Abbildung ist Ihnen möglicherweise aufgefallen, dass der Titel sowohl des Browsers als auch des Registerkartenbereichs dem URI für die XBAP entspricht. Der Titel ist zum einen lang und zum anderen weder ansprechend noch informativ. Aus diesem Grund gibt Ihnen Page die Möglichkeit, den Titel durch Festlegen der WindowTitle-Eigenschaft zu ändern. Ferner können Sie die Breite und Höhe der Browserfensters konfigurieren, indem Sie WindowWidth bzw. WindowHeight festlegen.

WindowTitle, WindowWidth und WindowHeight können deklarativ in Markup festgelegt werden, wie im folgenden Beispiel zu sehen.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage"
    WindowTitle="Page Title"
    WindowWidth="500"
    WindowHeight="200">
  Hello, from the XBAP HomePage!
</Page>

Das Ergebnis ist in der folgenden Abbildung dargestellt.

Fenstertitel, Höhe, Breite

Eine typische XBAP umfasst mehrere Seiten. Mithilfe eines Hyperlink kann am einfachsten von einer Seite zur nächsten navigiert werden. Sie können einer Page deklarativ einen Hyperlink hinzufügen, indem Sie das Hyperlink-Element verwenden, was im folgenden Markup gezeigt wird.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page With Hyperlink"
  WindowWidth="250"
  WindowHeight="250">
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
  Navigate to Another Page
</Hyperlink>
</Page>

Für ein Hyperlink-Element benötigen Sie Folgendes:

  • Die Paket-URI der Page, zu der navigiert werden soll, wie im NavigateUri-Attribut angegeben.

  • Inhalt, auf den ein Benutzer klicken kann, um die Navigation einzuleiten, z. B. Text und Bilder (Informationen zum Inhalt, den das Hyperlink-Element enthalten kann, finden Sie unter Hyperlink).

Die folgende Abbildung stellt eine XBAP mit einer Page dar, die einen Hyperlink aufweist.

Seite mit Link

Erwartungsgemäß veranlasst Klicken auf den Hyperlink die XBAP dazu, zur Page zu navigieren, die durch das NavigateUri-Attribut bezeichnet wird. Darüber hinaus fügt die XBAP der Liste „Zuletzt besuchte Seiten“ in Internet Explorer einen Eintrag für die vorherige Page hinzu. Das wird in der folgenden Abbildung gezeigt.

Schaltflächen „Zurück“ und „Vorwärts“

Hyperlink unterstützt nicht nur die Navigation von einer Page zur nächsten, sondern auch die Fragmentnavigation.

Fragmentnavigation

Fragmentnavigation ist die Navigation zu einem Inhaltsfragment auf entweder der aktuellen Page oder einer anderen Page. In WPF entspricht ein Inhaltsfragment dem Inhalt, der in einem benannten Element enthalten ist. Ein benanntes Element ist ein Element, dessen Name-Attribut festgelegt wurde. Im folgenden Markup wird ein benanntes TextBlock-Element gezeigt, das ein Inhaltsfragment enthält.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowTitle="Page With Fragments" >
<!-- Content Fragment called "Fragment1" -->
<TextBlock Name="Fragment1">
  Ea vel dignissim te aliquam facilisis ...
</TextBlock>
</Page>

Damit ein Hyperlink zu einem Inhaltsfragment navigiert, muss das NavigateUri-Attribut Folgendes einschließen:

  • Den URI der Page mit dem Inhaltsfragment, zu dem navigiert werden soll.

  • Ein „#“-Zeichen.

  • Den Namen des Elements auf der Page, die das Inhaltsfragment enthält.

Ein Fragment-URI hat das folgende Format.

Seiten-URI # Elementname

Im Folgenden finden Sie ein Beispiel für einen Hyperlink, der für die Navigation zu einem Inhaltsfragment konfiguriert ist.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page That Navigates To Fragment" >
<Hyperlink NavigateUri="PageWithFragments.xaml#Fragment1">
  Navigate To pack Fragment
</Hyperlink>
</Page>

Hinweis

In diesem Abschnitt wird die standardmäßige Implementierung der Fragmentnavigation in WPF beschrieben. WPF ermöglicht Ihnen darüber hinaus die Implementierung eines eigenen Schemas für die Fragmentnavigation, was zumindest teilweise die Behandlung des NavigationService.FragmentNavigation-Ereignisses erfordert.

Wichtig

Sie können nur dann zu Fragmenten auf Loose XAML-Seiten (nur Markup enthaltenden XAML-Dateien mit Page als Stammelement) navigieren, wenn die Seiten mithilfe von HTTP gesucht werden können.

Eine Loose XAML-Seite kann jedoch zu ihren eigenen Fragmenten navigieren.

Während ein Hyperlink einem Benutzer das Einleiten der Navigation zu einer bestimmten Page erlaubt, wird die Arbeit, die Seite aufzuspüren und herunterzuladen, von der NavigationService-Klasse übernommen. Im Grunde stellt NavigationService die Fähigkeit zum Verarbeiten einer Navigationsanforderung im Auftrag von Clientcode zur Verfügung, wie etwa des Hyperlink. Darüber hinaus implementiert NavigationService Unterstützung auf höherer Ebene zum Nachverfolgen und Beeinflussen einer Navigationsanforderung.

Wenn auf einen Hyperlink geklickt wird, ruft WPF NavigationService.Navigate auf, um die Page unter dem angegebenen Paket-URI aufzufinden und herunterzuladen. Die heruntergeladene Page wird in eine Struktur von Objekten konvertiert, deren Stammobjekt eine Instanz der heruntergeladenen Page ist. Ein Verweis auf das Page-Stammobjekt wird in der NavigationService.Content-Eigenschaft gespeichert. Der Paket-URI für den Inhalt, zu dem navigiert wurde, wird in der Eigenschaft NavigationService.Source gespeichert, während die NavigationService.CurrentSource den Paket-URI für die letzte Seite speichert, zu der navigiert wurde.

Hinweis

Eine WPF-Anwendung kann mehr als einen aktuell aktiven NavigationService aufweisen. Weitere Informationen finden Sie unter Navigationshosts weiter unten in diesem Thema.

Programmgesteuerte Navigation mit dem Navigationsdienst

Sie brauchen nichts über den NavigationService zu wissen, wenn die Navigation deklarativ in Markup mithilfe von Hyperlink implementiert wird, da Hyperlink den NavigationService in Ihrem Auftrag verwendet. Dies bedeutet, dass Hyperlinkden Navigationsdienst des Navigationshosts finden und verwenden kann, um eine Navigationsanforderung zu verarbeiten, solange entweder das direkte oder das indirekte übergeordnete Element von Hyperlink ein Navigationshost ist (siehe Navigationshosts).

Es gibt jedoch Situationen, in denen Sie den NavigationService direkt verwenden müssen, etwa die folgenden:

  • Wenn Sie eine Page mithilfe eines nicht parameterlosen Konstruktors instanziieren müssen.

  • Wenn Sie Eigenschaften auf der Page festlegen müssen, bevor Sie dorthin navigieren.

  • Wenn die Page, zu der navigiert werden soll, nur zur Laufzeit bestimmt werden kann.

In diesen Situationen müssen Sie Code schreiben, um die Navigation programmgesteuert einzuleiten, indem Sie die Navigate-Methode des NavigationService-Objekts aufrufen. Dazu ist es erforderlich, einen Verweis auf einen NavigationService abzurufen.

Abrufen eines Verweises auf NavigationService

Aus Gründen, die im Abschnitt Navigationshosts behandelt werden, kann eine WPF-Anwendung mehr als einen NavigationService aufweisen. Dies bedeutet, dass Ihr Code eine Möglichkeit benötigt, einen NavigationService zu finden, normalerweise ist das der NavigationService, der für die Navigation zur aktuellen Page verwendet wurde. Sie können einen Verweis auf einen NavigationService abrufen, indem Sie die staticNavigationService.GetNavigationService-Methode aufrufen. Um den NavigationService zu erhalten, der für die Navigation zu einer bestimmten Pageverwendet wurde, übergeben Sie einen Verweis auf die Page als Argument der GetNavigationService-Methode. Im folgenden Code wird gezeigt, wie Sie den NavigationService für die aktuelle Page abrufen.

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = NavigationService.GetNavigationService(this);
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = NavigationService.GetNavigationService(Me)

Als Abkürzung für die Suche des NavigationService nach einer Page implementiert Page die Eigenschaft NavigationService. Dies wird im folgenden Beispiel gezeigt.

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = this.NavigationService;
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = Me.NavigationService

Hinweis

Eine Page kann nur einen Verweis auf ihren NavigationService abrufen, wenn Page das Loaded-Ereignis auslöst.

Programmgesteuerte Navigation zu einem Seitenobjekt

Im folgenden Beispiel wird gezeigt, wie Sie den NavigationService verwenden, um programmgesteuert zu einer Page zu navigieren. Programmgesteuerte Navigation wird benötigt, da die Page, zu der navigiert wird, nur über einen einzelnen, nicht parameterlosen Konstruktor instanziiert werden kann. Die Page mit dem nicht parameterlosen Konstruktor wird im folgenden Markup und Code dargestellt.

<Page
    x:Class="SDKSample.PageWithNonDefaultConstructor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="PageWithNonDefaultConstructor">
  
  <!-- Content goes here -->
  
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithNonDefaultConstructor : Page
    {
        public PageWithNonDefaultConstructor(string message)
        {
            InitializeComponent();

            this.Content = message;
        }
    }
}

Namespace SDKSample
    Partial Public Class PageWithNonDefaultConstructor
        Inherits Page
        Public Sub New(ByVal message As String)
            InitializeComponent()

            Me.Content = message
        End Sub
    End Class
End Namespace

Die Page, die zur Page mit dem nicht parameterlosen Konstruktor navigiert, wird im folgenden Markup und Code dargestellt.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSNavigationPage">

  <Hyperlink Click="hyperlink_Click">
    Navigate to Page with Non-Default Constructor
  </Hyperlink>

</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSNavigationPage : Page
    {
        public NSNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the page to navigate to
            PageWithNonDefaultConstructor page = new PageWithNonDefaultConstructor("Hello!");

            // Navigate to the page, using the NavigationService
            this.NavigationService.Navigate(page);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Instantiate the page to navigate to
            Dim page As New PageWithNonDefaultConstructor("Hello!")

            ' Navigate to the page, using the NavigationService
            Me.NavigationService.Navigate(page)
        End Sub
    End Class
End Namespace

Wenn auf den Hyperlink auf dieser Page geklickt wird, wird die Navigation eingeleitet, indem die Page, die das Navigationsziel bildet, mithilfe des nicht parameterlosen Konstruktors und durch Aufrufen der Methode NavigationService.Navigate instanziiert wird. Navigate akzeptiert einen Verweis auf das Objekt, zu dem der NavigationService navigieren soll, anstelle eines Paket-URIs.

Programmgesteuerte Navigation mit einem Paket-URI

Wenn Sie einen Paket-URI programmgesteuert erstellen müssen (etwa, wenn der Paket-URI nur zur Laufzeit bestimmt werden kann), können Sie die NavigationService.Navigate-Methode verwenden. Dies wird im folgenden Beispiel gezeigt.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSUriNavigationPage">
  <Hyperlink Click="hyperlink_Click">Navigate to Page by Pack URI</Hyperlink>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSUriNavigationPage : Page
    {
        public NSUriNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Create a pack URI
            Uri uri = new Uri("AnotherPage.xaml", UriKind.Relative);

            // Get the navigation service that was used to
            // navigate to this page, and navigate to
            // AnotherPage.xaml
            this.NavigationService.Navigate(uri);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSUriNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Create a pack URI
            Dim uri As New Uri("AnotherPage.xaml", UriKind.Relative)

            ' Get the navigation service that was used to 
            ' navigate to this page, and navigate to 
            ' AnotherPage.xaml
            Me.NavigationService.Navigate(uri)
        End Sub
    End Class
End Namespace

Aktualisieren der aktuellen Seite

Eine Page wird nicht heruntergeladen, wenn sie den gleichen Paket-URI aufweist, der in der NavigationService.Source-Eigenschaft gespeichert ist. Wenn Sie WPF zwingen möchten, die aktuelle Seite erneut herunterzuladen, können Sie die NavigationService.Refresh-Methode aufrufen, wie im folgenden Beispiel gezeigt.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSRefreshNavigationPage">
 <Hyperlink Click="hyperlink_Click">Refresh this page</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSRefreshNavigationPage : Page
    {

Namespace SDKSample
    Partial Public Class NSRefreshNavigationPage
        Inherits Page
        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Refresh();
        }
    }
}
        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Refresh()
        End Sub
    End Class
End Namespace

Wie Sie sehen, gibt es viele Möglichkeiten zum Einleiten der Navigation. Nachdem die Navigation initiiert wurde und während sie ausgeführt wird, können Sie die Navigation mit den folgenden Ereignissen, die von NavigationService implementiert werden, nachverfolgen und beeinflussen:

  • Navigating. Tritt ein, wenn eine neue Navigation angefordert wird. Kann zum Abbrechen der Navigation verwendet werden.

  • NavigationProgress Tritt regelmäßig während eines Downloadvorgangs auf, um Informationen zum Navigationsstatus bereitzustellen.

  • Navigated Tritt ein, nachdem die Seite gefunden und heruntergeladen wurde.

  • NavigationStopped Tritt ein, nachdem die Navigation (durch Aufrufen von StopLoading) beendet wurde oder wenn eine neue Navigation angefordert wird, während die aktuelle Navigation noch ausgeführt wird.

  • NavigationFailed Tritt ein, wenn ein Fehler ausgelöst wird, während zum angeforderten Inhalt navigiert wird.

  • LoadCompleted Tritt ein, wenn der Inhalt, zu dem navigiert wurde, geladen und analysiert wird und mit dem Rendering begonnen wurde.

  • FragmentNavigation. Tritt ein, wenn die Navigation zu einem Inhaltsfragment beginnt, was in folgenden Fällen geschieht:

    • Sofort, falls sich das gewünschte Fragment im aktuellen Inhalt befindet.

    • Nachdem der Inhalt der Quelldatei geladen wurde und sich das gewünschte Fragment in einem anderen Inhalt befindet.

Die Navigationsereignisse werden in der Reihenfolge ausgelöst, die in der folgenden Abbildung dargestellt wird.

Flussdiagramm mit Seitennavigation

Im Allgemeinen muss sich eine Page nicht mit diesen Ereignissen abgeben. Es ist viel wahrscheinlicher, dass sich eine Anwendung mit ihnen befasst. Aus diesem Grund werden diese Ereignisse ebenfalls von der Application-Klasse ausgelöst:

Jedes Mal, wenn der NavigationService ein Ereignis auslöst, löst die Application-Klasse das entsprechende Ereignis aus. Frame und NavigationWindow bieten die gleichen Ereignisse zum Erkennen von Navigation innerhalb ihres jeweiligen Bereichs.

In manchen Fällen können diese Ereignisse für eine Page von Interesse sein. Beispielsweise könnte eine Page das NavigationService.Navigating-Ereignis verarbeiten, um zu bestimmen, ob die Navigation fort von der Seite unterbunden werden soll oder nicht. Dies wird im folgenden Beispiel gezeigt.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.CancelNavigationPage">
  <Button Click="button_Click">Navigate to Another Page</Button>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class CancelNavigationPage : Page
    {
        public CancelNavigationPage()
        {
            InitializeComponent();

            // Can only access the NavigationService when the page has been loaded
            this.Loaded += new RoutedEventHandler(CancelNavigationPage_Loaded);
            this.Unloaded += new RoutedEventHandler(CancelNavigationPage_Unloaded);
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Navigate(new Uri("AnotherPage.xaml", UriKind.Relative));
        }

        void CancelNavigationPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating += new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void CancelNavigationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating -= new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            // Does the user really want to navigate to another page?
            MessageBoxResult result;
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo);

            // If the user doesn't want to navigate away, cancel the navigation
            if (result == MessageBoxResult.No) e.Cancel = true;
        }
    }
}

Namespace SDKSample
    Partial Public Class CancelNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()

            ' Can only access the NavigationService when the page has been loaded
            AddHandler Loaded, AddressOf CancelNavigationPage_Loaded
            AddHandler Unloaded, AddressOf CancelNavigationPage_Unloaded
        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Navigate(New Uri("AnotherPage.xaml", UriKind.Relative))
        End Sub

        Private Sub CancelNavigationPage_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            AddHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub CancelNavigationPage_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            RemoveHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub NavigationService_Navigating(ByVal sender As Object, ByVal e As NavigatingCancelEventArgs)
            ' Does the user really want to navigate to another page?
            Dim result As MessageBoxResult
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo)

            ' If the user doesn't want to navigate away, cancel the navigation
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End Sub
    End Class
End Namespace

Wenn Sie einen Handler für ein Navigationsereignis von einer Page registrieren, wie im vorherigen Beispiel zu sehen, dann müssen Sie die Registrierung des Ereignishandlers ebenso aufheben. Wenn Sie das versäumen, kann das Nebeneffekte im Hinblick darauf auslösen, wie die WPF-Navigation die Page-Navigation im Journal speichert.

Aufzeichnung der Navigation mithilfe des Journals

WPF verwendet zwei Stapel, um die Seiten zu speichern, von denen Sie weg navigiert sind: jeweils einen Stapel für die Rückwärts- und einen Stapel für die Vorwärtsnavigation. Wenn Sie von der aktuellen Page zu einer neuen Page oder zu einer vorhandenen Page weiterleiten, wird die aktuelle Page zum Stapel für die Rückwärtsnavigation hinzugefügt. Wenn Sie von der aktuellen Page zurück zur vorherigen Page navigieren, wird die aktuelle Page dem Stapel für die Vorwärtsnavigation hinzugefügt. Der Rückwärts- und der Vorwärtsstapel sowie die Funktion zum Verwalten der Stapel werden zusammen als das Journal bezeichnet. Jedes Element in den beiden Stapeln stellt eine Instanz der JournalEntry-Klasse dar und wird als Journaleintrag bezeichnet.

Prinzipiell funktioniert das Journal auf dieselbe Weise wie die Schaltflächen Zurück und Vorwärts im Internet-Explorer. Diese sind in der folgenden Abbildung dargestellt.

Schaltflächen „Zurück“ und „Vorwärts“

Für XBAPs, die von Internet Explorer gehostet werden, integriert WPF das Journal in die Navigationsoberfläche von Internet Explorer. Auf diese Weise können Benutzer zu Seiten in einer XBAP navigieren, indem sie die Schaltflächen Zurück, Vorwärts und Zuletzt besuchte Seiten in Internet-Explorer verwenden.

Wichtig

Wenn ein Benutzer in Internet-Explorer von einer XBAP weg und wieder dorthin zurück navigiert, bleiben im Journal nur die Journaleinträge für Seiten erhalten, für die kein Keepalive durchgeführt wurde. Eine Erklärung, wie Sie Seiten beibehalten, finden Sie unter Seitenlebensdauer und das Journal weiter unten in diesem Thema.

Standardmäßig ist der Text für jede Page, die in der Liste Zuletzt besuchte Seiten von Internet Explorer aufgeführt ist, der URI für die Page. In vielen Fällen ist das für den Benutzer nicht besonders sinnvoll. Sie können den Text jedoch mithilfe einer der folgenden Optionen ändern:

  1. Dem angefügten JournalEntry.Name-Attributwert

  2. Dem Page.Title-Attributwert

  3. Dem Page.WindowTitle-Attributwert und dem URI für die aktuelle Page

  4. Dem URI für die aktuelle Page (Standardwert)

Die Reihenfolge, in der die Optionen aufgeführt sind, entspricht der Rangfolge zum Suchen von Text. Wenn beispielsweise JournalEntry.Name festgelegt ist, werden die anderen Werte ignoriert.

Im folgenden Beispiel wird das Page.Title-Attribut verwendet, um den Text zu ändern, der für einen Journaleintrag angezeigt wird.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.PageWithTitle"
    Title="This is the title of the journal entry for this page.">
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithTitle : Page
    {

Namespace SDKSample
    Partial Public Class PageWithTitle
        Inherits Page
    }
}
    End Class
End Namespace

Zwar kann der Benutzer mithilfe der Schaltflächen Zurück, Vorwärts und Zuletzt besuchte Seiten in Internet-Explorer im Journal navigieren, jedoch können Sie auch sowohl mit dem deklarativen als auch mit dem programmgesteuerten Mechanismus von WPF im Journal navigieren. Ein Grund dafür besteht darin, auf den Seiten benutzerdefinierte Navigationsoberflächen zur Verfügung zu stellen.

Sie können die Unterstützung der Journalnavigation deklarativ hinzufügen, indem Sie die Navigationsbefehle verwenden, die von NavigationCommands verfügbar gemacht werden. Im folgenden Beispiel wird die Verwendung des BrowseBack-Navigationsbefehls erläutert.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NavigationCommandsPage">
<Hyperlink Command="NavigationCommands.BrowseBack">Back</Hyperlink>
<Hyperlink Command="NavigationCommands.BrowseForward">Forward</Hyperlink>
</Page>

Sie können programmgesteuert mit einem der folgenden Member der NavigationService-Klasse im Journal navigieren:

Das Journal kann auch programmgesteuert geändert werden, wie in Beibehalten des Inhaltszustands über den Navigationsverlauf weiter unten in diesem Thema erläutert wird.

Seitenlebensdauer und das Journal

Stellen Sie sich eine XBAP mit mehreren Seiten vor, die umfangreichen Inhalt enthalten, einschließlich Grafiken, Animationen und Medien. Die Speicherbeanspruchung für Seiten wie diese könnte recht groß sein, insbesondere, wenn Video- und Audiomedien verwendet werden. Da das Journal Seiten „speichert“, zu denen navigiert wurde, könnte eine solche XBAP schnell eine beträchtliche Menge Speicherplatz belegen.

Aus diesem Grund besteht das Standardverhalten des Journals im Speichern von Page-Metadaten in jedem Journaleintrag, statt auf ein Page-Objekt zu verweisen. Wenn zu einem Journaleintrag navigiert wird, werden seine Page-Metadaten verwendet, um eine neue Instanz der angegebenen Page zu erstellen. Entsprechend hat jede Page, zu der navigiert wird, die in der folgenden Abbildung dargestellte Lebensdauer.

Seitenlebensdauer

Zwar kann das Standardverhalten des Journals zu einer geringeren Speicherauslastung führen, die Leistung beim Rendern pro Seite wird aber möglicherweise herabgesetzt. Das erneute Instanziieren einer Page kann zeitaufwändig sein, insbesondere bei umfangreichem Inhalt. Wenn Sie eine Page-Instanz im Journal aufbewahren müssen, können Sie hierzu die folgenden beiden Techniken nutzen. Erstens können Sie programmgesteuert zu einem Page-Objekt navigieren, indem Sie die NavigationService.Navigate-Methode aufrufen.

Zweitens können Sie festlegen, dass WPF eine Instanz einer Page im Journal aufbewahrt, indem Sie die Eigenschaft KeepAlive auf true festlegen (der Standardwert ist false). Wie im folgenden Beispiel gezeigt, können Sie KeepAlive deklarativ in Markup festlegen.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.KeepAlivePage"
    KeepAlive="True">
  
  An instance of this page is stored in the journal.
  
</Page>

Die Lebensdauer einer aktiv beibehaltenen Page unterscheidet sich geringfügig von der einer nicht beibehaltenen Seite. Beim ersten Navigieren zu einer Page, die beibehalten wird, wird die Seite instanziiert, ganz wie eine Page, die nicht beibehalten wird. Da jedoch eine Instanz der Page im Journal beibehalten wird, wird sie für die Dauer ihrer Aufbewahrung im Journal nicht mehr instanziiert. Dementsprechend sollten Sie, wenn die Initialisierungslogik einer Page bei jedem Navigieren zu der Page aufgerufen werden muss, sie aus dem Konstruktor in den Handler für das Loaded-Ereignis auslagern. Wie in der folgenden Abbildung gezeigt, werden die Ereignisse Loaded und Unloaded trotzdem jedes Mal ausgelöst, wenn die Navigation hin zu bzw. weg von einer Page erfolgt.

Auslösen der Ereignisse „Loaded“ und „Unloaded“

Wenn eine Page nicht aktiv beibehalten wird, sollten Sie Folgendes unterlassen:

  • Speichern eines Verweises auf die Seite oder einen Teil der Seite

  • Registrieren von Ereignishandlern für Ereignisse, die nicht von ihr implementiert werden

Mit jedem dieser Schritte werden Verweise erstellt, die erzwingen, dass die Page im Speicher aufbewahrt wird, auch nachdem sie aus dem Journal entfernt wurde.

Im allgemeinen sollten Sie dem Page-Standardverhalten, eine Page nicht aktiv beizubehalten, den Vorzug geben. Dies zieht jedoch Auswirkungen auf den Zustand nach sich, die im nächsten Abschnitt erörtert werden.

Beibehalten des Inhaltszustands über den Navigationsverlauf

Angenommen, eine Page wird nicht aktiv beibehalten und verfügt über Steuerelemente, die Benutzerdaten erfassen. Wie wirkt es sich auf die Daten aus, wenn ein Benutzer von der Page weg und dorthin zurück navigiert? Aus Gründen der Benutzererfahrung sollte der Benutzer erwarten, dass die zuvor eingegebenen Daten angezeigt werden. Da mit jeder Navigation eine neue Instanz der Page erstellt wird, werden die Steuerelemente, die die Daten erfasst haben, jedoch neu instanziiert, und die Daten gehen verloren.

Das Journal unterstützt jedoch das Speichern von Daten über Page-Navigationen hinweg, einschließlich Steuerelementdaten. Insbesondere fungiert der Journaleintrag für jede Page als vorübergehender Container für den Status der zugeordneten Page. In den folgenden Schritten wird beschrieben, wie diese Unterstützung verwendet wird, wenn von einer Page weg navigiert wird:

  1. Dem Journal wird ein Eintrag für die aktuelle Page hinzugefügt.

  2. Der Status der Page wird im Journaleintrag für die betreffende Seite gespeichert, die dem Stapel für die Rückwärtsnavigation hinzugefügt wird.

  3. Es wird zur neuen Page navigiert.

Wenn mithilfe des Journals wieder zur ursprünglichen Page zurück navigiert wird, werden die folgenden Schritte ausgeführt:

  1. Die Page (der oberste Journaleintrag auf dem Stapel für die Rückwärtsnavigation) wird instanziiert.

  2. Die Page wird mit dem Status aktualisiert, der zusammen mit dem Journaleintrag für die Page gespeichert worden war.

  3. Es wird zurück zur Page navigiert.

WPF nutzt diese Unterstützung automatisch, wenn die folgenden Steuerelemente auf einer Page verwendet werden:

Wenn eine Page diese Steuerelemente verwendet, bleiben die in sie eingegebenen Daten über Page-Navigationsvorgänge hinweg gespeichert, wie in der folgenden Abbildung anhand der LieblingsfarbeListBox dargestellt ist.

Seite mit Steuerelementen, die den Zustand speichern

Wenn eine Page andere Steuerelemente aufweist als die oben aufgeführten oder wenn ein Zustand in benutzerdefinierten Objekten gespeichert wird, müssen Sie Code schreiben, durch den das Journal den Zustand über Page-Navigationen hinweg speichert.

Wenn Sie kleinteilige Statusinformationen über Page-Navigationsvorgänge hinweg speichern müssen, können Sie Abhängigkeitseigenschaften (siehe dazu DependencyProperty) verwenden, die mit dem FrameworkPropertyMetadata.Journal-Metadatenflag konfiguriert werden.

Wenn der Zustand, den Ihre Page über Navigationsvorgänge hinweg speichern muss, aus mehreren Informationsstücken besteht, kann sich das Kapseln Ihres Zustands in einer einzelnen Klasse und Implementieren der IProvideCustomContentState-Schnittstelle als weniger codeintensiv erweisen.

Wenn Sie durch verschiedene Zustände einer einzelnen Page navigieren müssen, ohne von der Page selbst weg zu navigieren, können Sie IProvideCustomContentState und NavigationService.AddBackEntry verwenden.

Cookies

Eine andere Möglichkeit, wie WPF-Anwendungen Daten speichern können, sind Cookies, die mithilfe der Methoden SetCookie und GetCookie erstellt, aktualisiert und gelöscht werden. Die Cookies, die Sie in WPF erstellen können, sind mit den Cookies identisch, die von anderen Webanwendungen verwendet werden. Cookies bestehen aus willkürlichen Daten, die von einer Anwendung entweder während oder über Anwendungssitzungen hinweg auf einem Clientcomputer gespeichert werden. Cookiedaten weisen meist das folgende Format eines Name-Wert-Paares auf.

Name = Wert

Wenn die Daten an SetCookie übergeben werden, wird zusammen mit dem Uri des Standorts, für den das Cookie festgelegt werden soll, speicherintern ein Cookie erstellt, das nur für die Dauer der aktuellen Anwendungssitzung verfügbar ist. Diese Art von Cookies wird als Sitzungscookie bezeichnet.

Wenn Sie ein Cookie über Anwendungssitzungen speichern möchten, muss dem Cookie unter Verwendung des folgenden Formats ein Ablaufdatum hinzugefügt werden.

NAME = WERT ; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

Ein Cookie mit einem Ablaufdatum wird im Ordner „Temporäre Internetdateien“ der aktuellen Windows-Installation gespeichert, bis das Cookie abläuft. Ein solches Cookie wird als dauerhaftes Cookie bezeichnet, da es über Anwendungssitzungen hinweg erhalten bleibt.

Sitzungs- wie auch dauerhafte Cookies werden durch Aufrufen der GetCookie-Methode abgerufen, wobei der Uri des Speicherorts übergeben wird, an dem das Cookie mit der Methode SetCookie festgelegt wurde.

Im Folgenden werden einige der Methoden zum Unterstützen von Cookies in WPF dargestellt:

  • Eigenständige WPF-Anwendungen und XBAPs können Cookies erstellen und verwalten.

  • Auf Cookies, die von einer XBAP erstellt werden, kann vom Browser zugegriffen werden.

  • XBAPs aus derselben Domäne können Cookies erstellen und gemeinsam verwenden.

  • XBAPs und HTML-Seiten aus derselben Domäne können Cookies erstellen und gemeinsam verwenden.

  • Cookies werden gesendet, wenn XBAPs und Loose XAML-Seiten Webanforderungen vornehmen.

  • Die XBAPs der oberen Ebene und XBAPs, die in IFRAMES gehostet werden, können auf Cookies zugreifen.

  • Die Cookieunterstützung in WPF ist für alle unterstützten Browser gleich.

  • In Internet-Explorer wird die P3P-Richtlinie, die Cookies betrifft, von WPF berücksichtigt, insbesondere in Bezug auf XBAPs von Erst- und Drittanbietern.

Strukturierte Navigation

Wenn Sie Daten von einer Page an eine andere übergeben müssen, können Sie die Daten als Argumente an einen nicht parameterlosen Konstruktor der Page übergeben. Beachten Sie, dass Sie beim Verwenden dieser Technik die Page aktiv beibehalten müssen, andernfalls instanziiert WPF die Page neu mit dem parameterlosen Konstruktor, wenn Sie wieder zur Page navigieren.

Alternativ dazu kann Ihre Page Eigenschaften implementieren, die mit den zu übergebenden Daten festgelegt werden. Die Sache wird allerdings kompliziert, wenn eine Page Daten zurück an die Page übergeben muss, von der aus die Navigation zu ihr erfolgt ist. Das Problem besteht darin, dass die Navigation keine direkte Unterstützung für Mechanismen bietet, die garantieren können, dass zu einer Page zurückgekehrt wird, nachdem von ihr weg navigiert wurde. Im Grunde unterstützt die Navigation keine Semantik mit Aufruf/Rückgabe. Zum Lösen dieses Problems bietet WPF die PageFunction<T>-Klasse, die Sie verwenden können, um sicherzustellen, dass in einer vorhersagbaren und strukturierten Weise zu einer Page zurück navigiert wird. Weitere Informationen finden Sie unter Übersicht über die strukturierte Navigation.

Die NavigationWindow-Klasse

Bis jetzt haben Sie das Spektrum der Navigationsdienste kennengelernt, die Sie zum Erstellen von Anwendungen mit navigierbarem Inhalt normalerweise verwenden werden. Diese Dienste wurden im Kontext von XBAPs behandelt, obwohl sie nicht auf XBAPs beschränkt sind. Moderne Betriebssysteme und Windows-Anwendungen nutzen die Browsererfahrung moderner Benutzer, um die Navigation im Browserstil in eigenständige Anwendungen zu integrieren. Häufige Beispiele sind:

  • Word-Thesaurus: Navigieren durch verschiedene Benennungen (Synonyme)

  • Datei-Explorer: Navigieren in Dateien und Ordnern

  • Assistenten: Untergliedern einer komplexen Aufgabe in mehrere Seiten, zwischen denen navigiert werden kann. Ein Beispiel ist der Assistent für Windows-Komponenten, der das Hinzufügen und Entfernen von Windows-Features verarbeitet.

Um die Navigation im Browserstil in Ihre eigenständigen Anwendungen zu integrieren, können Sie die NavigationWindow-Klasse verwenden. NavigationWindow wird von Window abgeleitet und erweitert sie um die gleiche Navigationsunterstützung, die von XBAPs geboten wird. Verwenden Sie NavigationWindow entweder als Hauptfenster der eigenständigen Anwendung oder als sekundäres Fenster, z. B. ein Dialogfeld.

Zum Implementieren eines NavigationWindow verwenden Sie wie für die meisten Klassen der obersten Ebene in WPF (Window, Page usw.) eine Kombination aus Markup und CodeBehind. Dies wird im folgenden Beispiel gezeigt.

<NavigationWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MainWindow" 
    Source="HomePage.xaml"/>
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class MainWindow : NavigationWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Namespace SDKSample
    Partial Public Class MainWindow
        Inherits NavigationWindow
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

Dieser Code erstellt ein NavigationWindow, das automatisch zu einer Page (HomePage.xaml) navigiert, wenn das NavigationWindow geöffnet wird. Wenn das NavigationWindow das Hauptfenster der Anwendung darstellt, können Sie das StartupUri-Attribut verwenden, um es zu starten. Dies wird im folgenden Markup gezeigt.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

Die folgende Abbildung stellt das NavigationWindow als Hauptfenster einer eigenständigen Anwendung dar.

Hauptfenster

Aus der Abbildung können Sie ersehen, dass das NavigationWindow einen Titel besitzt, obwohl dieser im NavigationWindow-Implementierungscode aus dem vorstehenden Beispiel nicht festgelegt wurde. Vielmehr wird der Titel mithilfe der Eigenschaft WindowTitle festgelegt, was im folgenden Code zu sehen ist.

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="Home Page"
    WindowTitle="NavigationWindow">
</Page>

Das Festlegen der Eigenschaften WindowWidth und WindowHeight wirkt sich ebenfalls auf das NavigationWindow aus.

Normalerweise implementieren Sie Ihr eigenes NavigationWindow, wenn Sie entweder das Verhalten oder die Anzeige anpassen müssen. Wenn keines von beiden angepasst werden muss, können Sie eine Verknüpfung verwenden. Wenn Sie den Paket-URI einer Page als den StartupUri in einer eigenständigen Anwendung festlegen, erstellt Application automatisch ein NavigationWindow zum Hosten der Page. Im folgenden Markup wird gezeigt, wie Sie das aktivieren.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml" />

Wenn Sie ein sekundäres Anwendungsfenster (z. B. ein Dialogfeld) als NavigationWindow verwenden möchten, können Sie den Code aus dem folgenden Beispiel verwenden, um es zu öffnen.

// Open a navigation window as a dialog box
NavigationWindowDialogBox dlg = new NavigationWindowDialogBox();
dlg.Source = new Uri("HomePage.xaml", UriKind.Relative);
dlg.Owner = this;
dlg.ShowDialog();
' Open a navigation window as a dialog box
Dim dlg As New NavigationWindowDialogBox()
dlg.Source = New Uri("HomePage.xaml", UriKind.Relative)
dlg.Owner = Me
dlg.ShowDialog()

In der folgenden Abbildung wird das Ergebnis veranschaulicht.

Dialogfeld

Wie Sie sehen, zeigt NavigationWindow die Schaltflächen Zurück und Vorwärts, mit denen Benutzer im Journal navigieren können, im Stil von Internet-Explorer an. Wie in der folgenden Abbildung veranschaulicht, bieten diese Schaltflächen dieselbe Benutzererfahrung.

Schaltflächen „Zurück“ und „Vorwärts“ in NavigationWindow

Wenn Ihre Seite ihre eigene Unterstützung für die Journalnavigation und eine eigene Benutzeroberfläche mitbringt, können Sie die angezeigten Schaltflächen Zurück und Vorwärts ausblenden, die von NavigationWindow angezeigt werden, indem Sie den Wert der Eigenschaft ShowsNavigationUI auf false festlegen.

Alternativ können Sie die Anpassungsunterstützung in WPF verwenden, um die Benutzeroberfläche des NavigationWindow selbst zu ersetzen.

Die Frame-Klasse

Sowohl der Browser als auch NavigationWindow sind Fenster, die navigierbare Inhalte hosten. In einigen Fällen verfügen Anwendungen über Inhalt, der nicht von einem ganzen Fenster gehostet werden muss. Stattdessen kann solcher Inhalt in anderem Inhalt gehostet werden. Sie können navigierbaren Inhalt in anderen Inhalt einfügen, indem Sie die Frame-Klasse verwenden. Frame bietet die gleiche Unterstützung wie NavigationWindow und XBAPs.

Das folgende Beispiel zeigt, wie Sie einer Page deklarativ einen Frame hinzufügen, indem Sie das Frame-Element verwenden.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" />
</Page>

Dieses Markup legt das Source-Attribut des Frame-Element auf einen Paket-URI für die Page fest, zu der der Frame zu Anfang navigieren soll. Die folgende Abbildung zeigt eine XBAP mit einer Page, die über einen Frame verfügt, der zwischen verschiedenen Seiten navigiert hat.

Ein Frame, der zwischen mehreren Seiten navigiert hat

Sie brauchen Frame nicht nur innerhalb des Inhalts einer Page zu verwenden. Es ist ebenfalls gängige Praxis, einen Frame im Inhalt eines Window zu hosten.

Standardmäßig verwendet Frame nur sein eigenes Journal, wenn kein anderes angegeben ist. Wenn ein Frame Teil von Inhalten ist, die entweder in einem NavigationWindow oder einer XBAP gehostet sind, verwendet Frame das Journal, das zu dem NavigationWindow oder der XBAP gehört. Allerdings kommt es vor, dass ein Frame für das eigene Journal zuständig sein muss. Ein Grund dafür besteht darin, eine Navigation mithilfe des Journals innerhalb der Seiten zu ermöglichen, die durch einen Frame gehostet werden. Dies wird in der folgenden Abbildung verdeutlicht.

Frame- und Seitendiagramm

In diesem Fall können Sie den Frame für die Verwendung des eigenen Journals konfigurieren, indem Sie die Eigenschaft JournalOwnership des Frame auf OwnsJournal festlegen. Dies wird im folgenden Markup gezeigt.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" JournalOwnership="OwnsJournal" />
</Page>

In der folgenden Abbildung ist die Auswirkung der Navigation in einem Frame dargestellt, der sein eigenes Journal verwendet.

Ein Frame mit einem eigenen Journal

Beachten Sie, dass die Journaleinträge von der Navigationsbenutzeroberfläche im Frame anstelle von Internet-Explorer angezeigt werden.

Hinweis

Wenn ein Frame Teil von Inhalten ist, die in einem Window gehostet sind, verwendet Frame sein eigenes Journal und zeigt entsprechend seine eigene Navigationsbenutzeroberfläche an.

Wenn es für Ihre Benutzerumgebung erforderlich ist, dass ein Frame sein eigenes Journal bereitstellt, ohne die Navigationsbenutzeroberfläche anzuzeigen, können Sie die Navigationsbenutzeroberfläche ausblenden, indem Sie die NavigationUIVisibility auf Hidden festlegen. Dies wird im folgenden Markup gezeigt.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame 
  Source="FramePage1.xaml" 
  JournalOwnership="OwnsJournal" 
  NavigationUIVisibility="Hidden" />
</Page>

Frame und NavigationWindow sind Klassen, die als Navigationshosts bekannt sind. Ein Navigationshost ist eine Klasse, die zu Inhalt navigieren und diesen anzeigen kann. Zu diesem Zweck verwendet jeder Navigationshost seinen eigenen NavigationService und sein eigenes Journal. Die grundlegende Konstruktion eines Navigationshosts wird in der folgenden Abbildung gezeigt.

Navigatordiagramme

Im Grunde können NavigationWindow und Frame damit die gleiche Navigationsunterstützung wie eine XBAP bieten, die im Browser gehostet wird.

Nebst der Verwendung von NavigationService und eines Journals implementieren Navigationshosts die gleichen Member, die von NavigationService implementiert werden. Dies wird in der folgenden Abbildung verdeutlicht.

Ein Journal in einem Frame und einem Navigationsfenster (NavigationWindow)

Dies ermöglicht es Ihnen, Navigationsunterstützung direkt für sie zu programmieren. Sie können dies in Erwägung ziehen, wenn Sie eine benutzerdefinierte Navigationsbenutzeroberfläche für einen Frame bereitstellen müssen, der in einem Window gehostet wird. Darüber hinaus implementieren beide Typen zusätzliche navigationsbezogene Member, darunter BackStack (NavigationWindow.BackStack, Frame.BackStack) und ForwardStack (NavigationWindow.ForwardStack, Frame.ForwardStack), mit denen Sie die Journaleinträge im Stapel für die Rückwärtsnavigation bzw. dem Stapel für die Vorwärtsnavigation aufzählen können.

Wie bereits erwähnt, können in einer Anwendung mehrere Journale vorhanden sein. Die folgende Abbildung enthält ein Beispiel für die Fälle, in denen das auftreten kann.

Mehrere Journale in einer Anwendung

In diesem Thema wurden Page und Paket-XBAPs dazu verwendet, die verschiedenen Navigationsfunktionen von WPF zu veranschaulichen. Eine Page, die in eine Anwendung kompiliert wird, ist nicht die einzige Art Inhalt, zu der navigiert werden kann, und Paket-XBAPs sind nicht die einzige Möglichkeit zum Identifizieren von Inhalt.

Wie in diesem Abschnitt veranschaulicht wird, können Sie auch zu Loose XAML-Dateien, HTML-Dateien und Objekten navigieren.

Unter einer Loose XAML-Datei versteht man eine Datei mit den folgenden Eigenschaften:

  • Enthält nur XAML (d. h. keinen Code).

  • Verfügt über eine entsprechende Namespacedeklaration.

  • Hat die Dateierweiterung .xaml.

Betrachten Sie beispielsweise den folgenden Inhalt, der als Loose XAML-Datei „Person.xaml“ gespeichert ist.

<!-- Person.xaml -->
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <TextBlock FontWeight="Bold">Name:</TextBlock>
  <TextBlock>Nancy Davolio</TextBlock>
  <LineBreak />
  <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
  <TextBlock>Yellow</TextBlock>
</TextBlock>

Wenn Sie auf die Datei doppelklicken, wird der Browser geöffnet und navigiert zur Datei und zeigt den Inhalt an. Das wird in der folgenden Abbildung gezeigt.

Anzeige des Inhalts in der Datei „Person.XAML“

Sie können eine Loose XAML-Datei von folgenden Orten aus anzeigen:

  • Einer Website auf dem lokalen Computer, dem Intranet oder dem Internet

  • Einer UNC-Dateifreigabe (Universal Naming Convention)

  • Dem lokalen Datenträger

Eine Loose XAML-Datei kann den Favoriten des Browsers hinzugefügt werden oder die Homepage des Browsers darstellen.

Hinweis

Weitere Informationen zum Veröffentlichen und Starten von Loose XAML-Seiten finden Sie unter Bereitstellen von WPF-Anwendungen.

Loose XAML ist dahingehend eingeschränkt, dass nur Inhalt gehostet werden kann, dessen Ausführung mit teilweiser Vertrauenswürdigkeit sicher ist. Beispielsweise kann Window nicht das Stammelement einer Loose XAML-Datei sein. Weitere Informationen finden Sie unter WPF-Sicherheit mit teilweiser Vertrauenswürdigkeit.

Erwartungsgemäß können Sie auch zu HTML navigieren. Sie brauchen lediglich einen URI anzugeben, der das HTTP-Schema verwendet. Im folgenden XAML-Beispiel wird etwa ein Frame angezeigt, der zu einer HTML-Seite navigiert.

<Frame Source="http://www.microsoft.com/default.aspx" />

Für das Navigieren zu HTML sind besondere Berechtigungen erforderlich. Sie können beispielsweise nicht von einer XBAP aus navigieren, die in der Sandbox mit partieller Vertrauensstellung in der Internetzone ausgeführt wird. Weitere Informationen finden Sie unter WPF-Sicherheit mit teilweiser Vertrauenswürdigkeit.

Das WebBrowser-Steuerelement unterstützt HTML-Dokumenthosting, Navigation und die Interoperabilität von Skripts und verwaltetem Code. Ausführliche Informationen zum WebBrowser-Steuerelement finden Sie unter WebBrowser.

Wie bei Frame sind für das Navigieren zu HTML mithilfe von WebBrowser besondere Berechtigungen erforderlich. Von einer teilweise vertrauenswürdigen Anwendung können Sie nur zu HTML navigieren, das auf der Ursprungssite gespeichert ist. Weitere Informationen finden Sie unter WPF-Sicherheit mit teilweiser Vertrauenswürdigkeit.

Wenn ein Teil Ihrer Daten als benutzerdefinierte Objekte gespeichert sind, können Sie die Daten u. a. durch Erstellen einer Page mit Inhalten angezeigt werden, die an diese Objekte gebunden sind (siehe dazu Übersicht über Datenbindung). Wenn Sie eine ganze Seite nicht nur zu dem Zweck erstellen möchten, die Objekte anzuzeigen, können Sie stattdessen direkt zu ihnen navigieren.

Betrachten Sie die im folgenden Code implementierte Person-Klasse.

using System.Windows.Media;

namespace SDKSample
{
    public class Person
    {
        string name;
        Color favoriteColor;

        public Person() { }
        public Person(string name, Color favoriteColor)
        {
            this.name = name;
            this.favoriteColor = favoriteColor;
        }

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public Color FavoriteColor
        {
            get { return this.favoriteColor; }
            set { this.favoriteColor = value; }
        }
    }
}

Namespace SDKSample
    Public Class Person
        Private _name As String
        Private _favoriteColor As Color

        Public Sub New()
        End Sub
        Public Sub New(ByVal name As String, ByVal favoriteColor As Color)
            Me._name = name
            Me._favoriteColor = favoriteColor
        End Sub

        Public Property Name() As String
            Get
                Return Me._name
            End Get
            Set(ByVal value As String)
                Me._name = value
            End Set
        End Property

        Public Property FavoriteColor() As Color
            Get
                Return Me._favoriteColor
            End Get
            Set(ByVal value As Color)
                Me._favoriteColor = value
            End Set
        End Property
    End Class
End Namespace

Um zu ihr zu navigieren, rufen Sie die NavigationWindow.Navigate-Methode auf, wie im folgenden Code gezeigt.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.HomePage"
  WindowTitle="Page that Navigates to an Object">
<Hyperlink Name="hyperlink" Click="hyperlink_Click">
  Navigate to Nancy Davolio
</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Person person = new Person("Nancy Davolio", Colors.Yellow);
            this.NavigationService.Navigate(person);
        }
    }
}

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim person As New Person("Nancy Davolio", Colors.Yellow)
            Me.NavigationService.Navigate(person)
        End Sub
    End Class
End Namespace

In der folgenden Abbildung wird das Ergebnis veranschaulicht.

Eine Seite, die zu einer Klasse navigiert

Aus dieser Abbildung können Sie ersehen, dass nichts Nützliches angezeigt wird. Tatsächlich handelt es sich beim angezeigten Wert um den Rückgabewert der ToString-Methode für das Person-Objekt. Standardmäßig ist das der einzige Wert, den WPF zum Darstellen Ihres Objekts verwenden kann. Sie könnten die ToString-Methode überschreiben, um aussagekräftigere Informationen zu erhalten. Allerdings wird auch dann nur ein Zeichenfolgenwert zurückgegeben. Eine Technik, die Sie verwenden können, um die Darstellungsfunktionen von WPF zu nutzen, ist eine Datenvorlage. Sie können eine Datenvorlage implementieren, die WPF einem Objekt eines bestimmten Typs zuordnen kann. Im folgenden Code wird eine Datenvorlage für das Person-Objekt gezeigt.

<Application
    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.App"
    StartupUri="HomePage.xaml">

  <Application.Resources>

    <!-- Data Template for the Person Class -->
    <DataTemplate DataType="{x:Type local:Person}">
      <TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <TextBlock FontWeight="Bold">Name:</TextBlock>
        <TextBlock Text="{Binding Path=Name}" />
        <LineBreak />
        <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
        <TextBlock Text="{Binding Path=FavoriteColor}" />
      </TextBlock>
    </DataTemplate>
    
  </Application.Resources>

</Application>

In diesem Fall wird die Datenvorlage dem Person-Typ unter Verwendung der x:Type-Markuperweiterung im DataType-Attribut zugeordnet. Die Datenvorlage bindet dann TextBlock-Elemente (siehe TextBlock) an die Eigenschaften der Person-Klasse. Die folgende Abbildung stellt die aktualisierte Darstellung des Person-Objekts dar.

Navigieren zu einer Klasse mit einer Datenvorlage

Ein Vorteil dieser Technik liegt in der Konsistenz, die Ihnen die Wiederverwendung der Datenvorlage zur konsistenten Anzeige Ihrer Objekte in der gesamten Anwendung erlaubt.

Weitere Informationen zu Datenvorlagen finden Sie unter Übersicht über Datenvorlagen.

Sicherheit

Die WPF-Navigationsunterstützung ermöglicht es, dass über das Internet zu XBAPs navigiert werden kann, und sie ermöglicht Anwendungen das Hosten von Drittanbieterinhalten. Um sowohl Anwendungen als auch Benutzer vor bedrohlichem Verhalten zu schützen, stellt WPF eine Palette an Sicherheitsfeatures bereit, die unter Sicherheit und WPF-Sicherheit mit teilweiser Vertrauenswürdigkeit behandelt werden.

Siehe auch