次の方法で共有


ナビゲーションの概要

Windows Presentation Foundation (WPF) では、2 種類のアプリケーション (スタンドアロン アプリケーションと XAML ブラウザー アプリケーション (XBAP)) で使用できるブラウザー スタイルのナビゲーションがサポートされています。 ナビゲーション用にコンテンツをパッケージ化するため、WPF では Page クラスが提供されています。 Page 間は、Hyperlink を使用して宣言により、または NavigationService を使用してプログラムにより、ナビゲートできます。 WPF では、ナビゲート元のページを記憶し、それらのページに戻るために、履歴が使用されます。

PageHyperlinkNavigationService、および履歴は、WPF によって提供されるナビゲーション サポートの中核を形成しています。 この概要では、これらの機能について詳細に説明した後、Loose Extensible Application Markup Language (XAML) ファイル、HTML ファイル、オブジェクトへのナビゲーションなど、高度なナビゲーション サポートについて説明します。

注意

このトピックでは、"ブラウザー" という用語は、WPF アプリケーションをホストできるブラウザーのみを指し、現時点では、Microsoft Internet Explorer と Firefox が含まれます。 特定の WPF 機能が特定のブラウザーによってのみサポートされる場合は、ブラウザーのバージョンを示します。

このトピックでは、WPF における主なナビゲーション機能の概要を説明します。 これらの機能は、スタンドアロン アプリケーションと XBAP の両方で使用できますが、このトピックでは XBAP のコンテキストで説明します。

注意

このトピックは、XBAP のビルドと配置の方法については説明しません。 XBAP の詳細については、「WPF XAML ブラウザー アプリケーションの概要」を参照してください。

このセクションでは、ナビゲーションの次の側面について説明し、例を示します。

ページの実装

WPF では、.NET Framework オブジェクト、カスタム オブジェクト、列挙値、ユーザー コントロール、XAML ファイル、HTML ファイルなど、複数のコンテンツの種類に移動できます。 ただし、コンテンツをパッケージ化する最も一般的で便利な方法は、Page を使用することです。 さらに、Page では、ナビゲーション固有の機能が実装されており、それらの外観が強化され、開発が単純化されます。

Page を使用すると、次のようなマークアップを使用して、XAML コンテンツの移動可能なページを宣言によって実装できます。

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

XAML マークアップで実装される Page には、ルート要素として Page があり、WPF XML 名前空間の宣言が必要です。 Page 要素には、ナビゲートして表示するコンテンツが格納されます。 コンテンツは、次のマークアップに示されているように、Page.Content プロパティ要素を設定することによって追加します。

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

Page.Content には 1 つの子要素のみを含むことができます。前の例のコンテンツは、単一の文字列 "Hello, Page!" です。実際には、通常、レイアウト コントロールを子要素として使用して (「レイアウト」を参照)、コンテンツを格納および作成します。

Page 要素の子要素は、Page のコンテンツとみなされるため、明示的な Page.Content 宣言を使用する必要はありません。 次のマークアップは、前のサンプルの宣言と同等です。

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

この場合、Page.Content は、Page 要素の子要素を使用して自動的に設定されます。 詳細については、「WPF のコンテンツ モデル」を参照してください。

マークアップのみの Page は、コンテンツの表示に役立ちます。 ただし、Page では、ユーザーがページと対話するためのコントロールも表示でき、イベントを処理し、アプリケーション ロジックを呼び出すことによって、ユーザーの操作に応答できます。 対話形式の Page は、次の例に示されているように、マークアップと分離コードの組み合わせを使用して実装されます。

<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

マークアップ ファイルと分離コード ファイルを連携させるには、次の構成が必要です。

  • マークアップでは、Page 要素に x:Class 属性を含める必要があります。 アプリケーションのビルド時にマークアップ ファイルに x:Class が含まれていると、Microsoft Build Engine (MSBuild) により、x:Class 属性で指定された名前を持つ、Page から派生した partial クラスが作成されます。 このためには、XAML スキーマ (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml") に XML 名前空間宣言を追加する必要があります。 生成された partial クラスでは、InitializeComponent メソッドが実装されています。このメソッドを呼び出すと、イベントが登録され、マークアップで実装されるプロパティが設定されます。

  • 分離コードでは、クラスは、マークアップ内の x:Class 属性で指定されている名前を持つ partial クラスでなければなりません。また、Page から派生する必要があります。 これによって、分離コード ファイルと、アプリケーションのビルド時にマークアップ ファイル用に生成される partial クラスとが関連付けられます (「WPF アプリケーションのビルド」を参照)。

  • 分離コードでは、Page クラスによって実装されるコンストラクターで InitializeComponent メソッドが呼び出される必要があります。 InitializeComponent は、マークアップ ファイル用に生成された partial クラスによって実装されるもので、イベントの登録と、マークアップで定義されたプロパティの設定を実行します。

注意

Visual Studio を使用してプロジェクトに新しい Page を追加すると、ここで説明したように、マークアップと分離コードの両方を使用して Page が実装され、マークアップ ファイルと分離コード ファイル間の関連付けの作成に必要な構成が組み込まれます。

Page を作成したら、そこにナビゲートできます。 アプリケーションが最初にナビゲートする Page を指定するには、スタート Page を構成する必要があります。

スタート ページの構成

XBAP では、一定の量のアプリケーション インフラストラクチャをブラウザーでホストする必要があります。 WPF では、Application クラスは、必要なアプリケーション インフラストラクチャを確立するアプリケーション定義の一部です (「アプリケーション管理の概要」を参照)。

アプリケーション定義は、通常、MSBuild の ApplicationDefinition 項目として構成されたマークアップ ファイルで、マークアップとコードビハインドの両方を使用して実装されます。 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

XBAP では、アプリケーション定義を使用して、スタート Page を指定でき、これは、XBAP が起動されたときに自動的に呼び出される Page です。 このためには、目的の Page の Uniform Resource Identifier (URI) を StartupUri プロパティに設定します。

注意

ほとんどの場合、Page は、アプリケーションにコンパイルされるか、アプリケーションと共に配置されます。 このような場合、Page を識別する URI はパック URI であり、これは、"パック" スキームに準拠した URI です。 パック URI については、「WPF におけるパック URI」で詳しく説明します。 以下で説明する http スキームを使用してコンテンツにナビゲートすることもできます。

次の例に示されているように、マークアップで宣言することによって、StartupUri を設定することができます。

<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" />

この例では、StartupUri 属性は、HomePage.xaml を識別する相対パック URI で設定されます。 XBAP が起動されると、HomePage.xaml に自動的にナビゲートして、それが表示されます。 これを次の図に示します。これは、Web サーバーから起動された XBAP を示しています。

XBAP ページ

注意

XBAP の開発およびデプロイの詳細については、「WPF XAML ブラウザー アプリケーションの概要」および「WPF アプリケーションを配置する」を参照してください。

ホスト ウィンドウのタイトル、幅、および高さの構成

前の図を見て気付くことは、ブラウザーとタブのパネルのタイトルがどちらも XBAP の URI になっていることです。 このタイトルは、長いだけでなく、見た目が良いわけでも、有益な情報になっているわけでもありません。 このため、Page には、WindowTitle プロパティを設定することによってタイトルを変更する方法が用意されています。 さらに、WindowWidthWindowHeight を設定することによって、ブラウザー ウィンドウの幅と高さをそれぞれ構成することができます。

WindowTitleWindowWidth、および WindowHeight は、次の例に示されているように、マークアップで宣言して設定できます。

<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>

結果を次の例に示します。

ウィンドウのタイトル、高さ、幅

一般的な XBAP は、複数のページで構成されます。 あるページから別のページにナビゲートする最も簡単な方法は、Hyperlink を使用することです。 次のマークアップに示されているように、Hyperlink 要素を使用することによって、HyperlinkPage に宣言によって追加できます。

<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>

Hyperlink 要素には、次のものが必要です。

  • NavigateUri 属性によって使用される、ナビゲート先の Page のパック URI。

  • テキストやイメージなど、ユーザーがナビゲーションを開始するためにクリックできるコンテンツ (Hyperlink 要素に格納できるコンテンツについては、Hyperlink を参照)。

次の図では、Hyperlink がある Page を持つ XBAP を示します。

ハイパーリンクを含むページ

想定されるとおり、Hyperlink をクリックすると、XBAP は NavigateUri 属性によって識別される Page にナビゲートします。 さらに、XBAP により、前の Page のエントリが、Internet Explorer の [最近表示したページ] の一覧に追加されます。 これを次の図に示します。

[戻る] ボタンと [次に進む] ボタン

Page 間のナビゲーションのサポートだけでなく、Hyperlink ではフラグメント ナビゲーションもサポートされます。

フラグメント ナビゲーション

"フラグメント ナビゲーション" は、現在の Page または別の Page にあるコンテンツ フラグメントへのナビゲーションです。 WPF では、コンテンツ フラグメントは、名前付き要素に格納されるコンテンツです。 名前付き要素とは、Name 属性が設定されている要素です。 次のマークアップは、コンテンツ フラグメントを含む名前付き TextBlock 要素を示しています。

<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>

コンテンツ フラグメントにナビゲートする Hyperlink の場合、NavigateUri 属性に次のものを含める必要があります。

  • ナビゲート先のコンテンツ フラグメントがある Page の URI。

  • 「#」文字。

  • コンテンツ フラグメントがある Page 上の要素の名前。

フラグメント URI の形式は、次のとおりです。

PageURI # ElementName

コンテンツ フラグメントにナビゲートするように構成された Hyperlink の例を次に示します。

<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>

注意

このセクションでは、WPF での既定のフラグメント ナビゲーション実装について説明します。 WPF では、部分的に NavigationService.FragmentNavigation イベントの処理が必要な、独自のフラグメント ナビゲーション スキームを実装することもできます。

重要

HTTP でページを参照できる場合のみ、Loose XAML ページ (ルート要素として Page を含むマークアップのみの XAML ファイル) 内のフラグメントに移動できます。

ただし、Loose XAML ページは、自身のフラグメントに移動できます。

Hyperlink を使用すると、ユーザーは特定の Page へのナビゲーションを開始できますが、ページの位置を特定し、ダウンロードする作業は、NavigationService クラスによって実行されます。 基本的に、NavigationService では、Hyperlink などのクライアント コードの代わりに、ナビゲーション要求を処理できます。 さらに、NavigationService では、ナビゲーション要求の追跡と制御のための高レベルのサポートが実装されています。

Hyperlink がクリックされると、WPF で NavigationService.Navigate が呼び出され、指定されたパック URI にある Page が特定されて、ダウンロードされます。 ダウンロードされた Page は、ルート オブジェクトが、ダウンロードされた Page のインスタンスであるオブジェクト ツリーに変換されます。 ルート Page オブジェクトへの参照は、NavigationService.Content プロパティに格納されます。 ナビゲート先のコンテンツのパック URI は、NavigationService.Source プロパティに格納されますが、NavigationService.CurrentSource には、ナビゲート先の最後のページのパック URI が格納されます。

注意

WPF アプリケーションでは、現在アクティブな NavigationService を複数持つことが可能です。 詳細については、このトピックで後述する「ナビゲーション ホスト」を参照してください。

ナビゲーション サービスによるプログラム ナビゲーション

ナビゲーションが Hyperlink を使用してマークアップで宣言として実装される場合、開発者は NavigationService について知る必要はありません。Hyperlink では NavigationService が自動的に使用されるためです。 つまり、Hyperlink の直接的または間接的な親がナビゲーション ホストである限り (「ナビゲーション ホスト」を参照)、Hyperlink では、ナビゲーション ホストのナビゲーション サービスを発見および使用して、ナビゲーション要求を処理できます。

ただし、次のような場合は、NavigationService を直接使用する必要があります。

  • パラメーターなしではないコンストラクターを使用して Page をインスタンス化する必要がある場合。

  • ナビゲートする前に、Page のプロパティを設定する必要がある場合。

  • どの Page にナビゲートするかが、実行時まで決定できない場合。

このような場合は、NavigationService オブジェクトの Navigate メソッドを呼び出すことによって、プログラムでナビゲーションを開始するコードを記述する必要があります。 そのためには、NavigationService への参照を取得する必要があります。

NavigationService への参照の取得

ナビゲーション ホスト」のセクションで説明した理由から、WPF アプリケーションでは複数の NavigationService を持つことができます。 これは、NavigationService (通常は、現在の Page にナビゲートした NavigationService) を検索する手段がコードに必要なことを意味します。 NavigationService への参照は、staticNavigationService.GetNavigationService メソッドを呼び出すことによって取得できます。 特定の Page にナビゲートした NavigationService を取得するには、Page への参照を GetNavigationService メソッドの引数として渡します。 次のコードでは、現在の Page に対する NavigationService を取得する方法を示します。

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)

Page に対する NavigationService を検索するショートカットとして、Page では NavigationService プロパティが実装されています。 これを次の例に示します。

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

注意

PageLoaded イベントが発生したとき、Page ではその NavigationService に対する参照だけを取得できます。

ページ オブジェクトへのプログラム ナビゲーション

次の例では、NavigationService を使用して、Page にプログラムによってナビゲートする方法を示します。 ナビゲート先の Page は単一のパラメーターなしではないコンストラクターを使用しなければインスタンス化できないため、プログラム ナビゲーションが必要になります。 次のマークアップとコードでは、パラメーターなしではないコンストラクターを持つ Page を示します。

<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

次のマークアップとコードでは、パラメーターなしではないコンストラクターを持つ Page にナビゲートする Page を示します。

<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

この Page 上の Hyperlink がクリックされると、パラメーターなしではないコンストラクターを使用し、NavigationService.Navigate メソッドを呼び出して、ナビゲート先の Page をインスタンス化することによって、ナビゲーションが開始されます。 Navigate では、パック URI ではなく、NavigationService がナビゲートするオブジェクトへの参照が受け入れられます。

パック URI によるプログラム ナビゲーション

パック URI をプログラムによって構築する必要がある場合 (たとえば、実行時にのみパック URI を決定できる場合など) は、NavigationService.Navigate メソッドを使用できます。 これを次の例に示します。

<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

現在のページの更新

PageNavigationService.Source プロパティに格納されているパック URI と同じパック URI を持つ場合、このページはダウンロードされません。 WPF で現在のページを強制的に再びダウンロードするには、次の例に示されているように、NavigationService.Refresh メソッドを呼び出します。

<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

これまでに説明したように、ナビゲーションを開始するには多くの方法があります。 ナビゲーションが開始されると、ナビゲーション中に、NavigationService によって実装される次のイベントを使用して、ナビゲーションを追跡および制御できます。

  • Navigating= 新しいナビゲーションが要求されたときに発生します。 ナビゲーションのキャンセルに使用できます。

  • NavigationProgress= ナビゲーション進行状況の情報提供を目的として、ダウンロード中に定期的に発生します。

  • Navigated= ページの位置が特定され、ダウンロードされたときに発生します。

  • NavigationStopped= ナビゲーションが停止されたとき (StopLoading を呼び出すことによって)、または現在のナビゲーションの進行中に新しいナビゲーションが要求されたときに発生します。

  • NavigationFailed= 要求されたコンテンツにナビゲートするときにエラーが発生したときに発生します。

  • LoadCompleted= ナビゲート先のコンテンツが読み込まれ、解析されて、レンダリングが開始されたときに発生します。

  • FragmentNavigation= コンテンツ フラグメントへのナビゲーションが開始されたときに、次のタイミングで発生します。

    • 目的のフラグメントが現在のコンテンツの場合は、すぐに発生します。

    • 目的のフラグメントが別のコンテンツにある場合は、ソース コンテンツが読み込まれた後で発生します。

ナビゲーション イベントは、次の図に示されている順序で発生します。

ページ ナビゲーションのフロー チャート

一般に、Page は、これらのイベントの影響を受けません。 アプリケーションは、これらのイベントの影響を受ける可能性が高いため、これらのイベントは Application クラスによっても発生します。

NavigationService によってイベントが発生するたびに、Application クラスでは対応するイベントが発生します。 FrameNavigationWindow では、それぞれのスコープ内でナビゲーションを検出するために、同じイベントが提供されています。

場合によっては、Page がこれらのイベントに関与することがあります。 たとえば、Page では、NavigationService.Navigating イベントを処理して、そのページ以外へのナビゲーションをキャンセルするかどうかを決定することがあります。 これを次の例に示します。

<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

前の例で行ったように、Page からのナビゲーション イベントにハンドラーを登録した場合は、イベント ハンドラーの登録解除も行う必要があります。 解除しなかった場合、WPF ナビゲーションが履歴を使用して Page ナビゲーションを記憶する方法に関して、副作用が発生する可能性があります。

履歴によるナビゲーションの記憶

WPF では、戻るスタックと進むスタックの 2 つのスタックを使用して、ナビゲート元のページが記憶されます。 現在の Page から新しい Page にナビゲートするか、既存の Page に進むときは、現在の Page が "戻るスタック" に追加されます。 現在の Page から前の Page に戻るときは、現在の Page が "進むスタック" に追加されます。 戻るスタック、進むスタック、およびそれらを管理する機能を、まとめて履歴と呼びます。 戻るスタックと進むスタックの各項目は、JournalEntry クラスのインスタンスであり、"履歴エントリ" と呼ばれます。

概念として、履歴は、Internet Explorer の [戻る] ボタンと [進む] ボタンと同じように機能します。 これを次の図に示します。

[戻る] ボタンと [次に進む] ボタン

Internet Explorer によってホストされる XBAP の場合、WPF では、履歴が Internet Explorer のナビゲーション UI に統合されます。 これにより、ユーザーは、Internet Explorer の [戻る][進む][最近表示したページ] ボタンを使用して、XBAP のページ間をナビゲートできます。

重要

Internet Explorer では、ユーザーが XBAP との間でナビゲートすると、キープ アライブされなかったページの履歴項目のみが履歴に保持されます。 ページのキープ アライブについては、このトピックで後述する「ページの有効期間と履歴」を参照してください。

既定では、Internet Explorer の [最近表示したページ] の一覧に表示される各 Page のテキストは、Page の URI です。 多くの場合、これは、ユーザーにとって特に意味がありません。 幸い、次のオプションのいずれかを使用して、テキストを変更できます。

  1. 添付 JournalEntry.Name 属性値。

  2. Page.Title 属性値。

  3. Page.WindowTitle 属性値と現在の Page の URI。

  4. 現在の Page の URI。 (既定)

これらのオプションの順序は、テキスト検索の優先順位と一致します。 たとえば、JournalEntry.Name が設定された場合、他の値は無視されます。

次の例では、Page.Title 属性を使用して、履歴エントリに表示されるテキストを変更します。

<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

ユーザーは Internet Explorer の [戻る][進む][最近表示したページ] を使用して履歴をナビゲートできますが、WPF によって提供される宣言およびプログラム メカニズムを使用して履歴をナビゲートすることもできます。 これを行う理由の 1 つは、カスタム ナビゲーション UI をページに表示するためです。

NavigationCommands によって公開されるナビゲーション コマンドを使用して、宣言によって履歴ナビゲーション サポートを追加できます。 次の例では、BrowseBack ナビゲーション コマンドの使用方法を示します。

<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>

NavigationService クラスの次のメンバーのいずれかを使用して、プログラムによって履歴をナビゲートできます。

このトピックの「ナビゲーション履歴によるコンテンツ状態の保持」で説明するように、プログラムによって履歴を操作することも可能です。

ページの有効期間と履歴

グラフィックス、アニメーション、メディアなどのリッチ コンテンツを含む複数のページがある XBAP を考えてみます。 このようなページのメモリ使用量は、特にビデオやオーディオ メディアが使用されている場合、非常に大きくなることがあります。 履歴がナビゲート先のページを "記憶" することを考えると、このような XBAP はすぐに大量のメモリを消費する可能性があります。

このため、履歴の既定の動作では、Page オブジェクトへの参照ではなく、Page メタデータが各履歴エントリに格納されます。 履歴エントリにナビゲートすると、その Page メタデータを使用して、指定された Page の新しいインスタンスが作成されます。 その結果、ナビゲートされた各 Page の有効期間は、次の図のようになります。

ページの有効期間

既定の履歴動作を使用すると、メモリ消費量を節約できますが、特にコンテンツが多い場合は、ページごとのレンダリングのパフォーマンスが低下し、Page の再インスタンス化に時間がかかることがあります。 Page インスタンスを履歴に保持する必要がある場合、2 つの方法があります。 1 つ目の方法は、NavigationService.Navigate メソッドを呼び出すことによって、Page オブジェクトにプログラムでナビゲートできます。

2 つ目の方法は、KeepAlive プロパティを true (既定値は false) に設定することによって、WPF で Page のインスタンスを保持するように指定することができます。 次の例に示されているように、マークアップで宣言することによって、KeepAlive を設定することができます。

<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>

キープ アライブされる Page の有効期間とキープ アライブされないページの有効期間は、わずかに異なります。 キープ アライブされる Page に最初にナビゲートするときには、キープ アライブされない Page と同様にインスタンス化されます。 ただし、Page のインスタンスは履歴に保持されているため、履歴に保持されている限り、再びインスタンス化されることはありません。 その結果、Page へのナビゲートが行われるたびに呼び出す必要がある初期化ロジックが Page にある場合、それをコンストラクターから Loaded イベントのハンドラーに移動する必要があります。 このようにしても、次の図に示されているように、Page がナビゲート先およびナビゲート元になるたびに、それぞれ Loaded イベントと Unloaded イベントが発生します。

Loaded イベントと Unloaded イベントが発生した場合

Page がキープ ア ライブされないときは、次のいずれの操作も行わないでください。

  • ページへの参照、またはその一部への参照を格納する。

  • ページによって実装されていないイベントのイベント ハンドラーを登録する。

このいずれかの操作を行うと、Page が履歴から削除された後も、強制的にメモリに保持される参照が作成されます。

一般に、Page をキープ アライブしない Page の既定の動作を優先する必要があります。 ただし、これには、次のセクションで説明されている状態も関係します。

ナビゲーション履歴によるコンテンツの状態の保持

Page がキープ アライブされず、ユーザーからデータを収集するコントロールを持っている場合、ユーザーが Page からナビゲートしたり、そこに戻ったりすると、データに何が起きるでしょうか。 ユーザー エクスペリエンスの観点から見ると、ユーザーは以前に入力したデータが表示されることを期待します。 残念ながら、ナビゲーションごとに Page の新しいインスタンスが作成されるため、データを収集したコントロールが再インスタンス化されて、データは失われます。

幸いにも、履歴では Page ナビゲーション間をまたいでデータ (コントロール データなど) を記憶するサポートが提供されています。 具体的には、各 Page の履歴エントリは、関連付けられた Page の状態の一時的なコンテナーとして機能します。 次の手順では、Page からナビゲートするときに、このサポートがどのように使用されるかを示しています。

  1. 現在の Page のエントリが履歴に追加されます。

  2. Page の状態が、そのページの履歴エントリに格納され、戻るスタックに追加されます。

  3. 新しい Page にナビゲートします。

履歴を使用して、Page に戻るときには、次の手順が実行されます。

  1. Page (戻るスタックの先頭の履歴エントリ) がインスタンス化されます。

  2. Page の履歴エントリに格納された状態で、Page が更新されます。

  3. Page に戻ります。

Page で次のようなコントロールが使用されるとき、WPF では、このサポートが自動的に使用されます。

次の図の [Favorite Color]ListBox で示されているように、Page でこれらのコントロールが使用される場合、これらに入力されたデータは、Page ナビゲーション間をまたいで記憶されます。

状態を記憶するコントロールがあるページ

前述の一覧にないコントロールが Page に含まれている場合や、状態情報がカスタム オブジェクトに格納される場合、Page ナビゲーション間をまたいで履歴に状態を記憶するコードを記述する必要があります。

Page ナビゲーション間をまたいで少量の状態情報を記憶する必要がある場合、FrameworkPropertyMetadata.Journal メタデータ フラグを使用して構成される依存関係プロパティ (DependencyProperty を参照) を使用できます。

ナビゲーション間をまたいで状態を記憶する必要がある Page が複数のデータで構成される場合、状態情報を 1 つのクラスにカプセル化して、IProvideCustomContentState インターフェイスを実装すると、コードが簡単になることがあります。

Page 自体からはナビゲートせずに、1 つの Page のさまざまな状態をナビゲートする必要がある場合には、IProvideCustomContentStateNavigationService.AddBackEntry を使用できます。

クッキー

WPF アプリケーションでデータを格納するもう 1 つの方法は、クッキーを使用することです。Cookie は、SetCookie メソッドと GetCookie メソッドを使用して、作成、更新、および削除されます。 WPF で作成できる Cookie は、他の種類の Web アプリケーションが使用する Cookie と同じです。クッキーは、アプリケーション セッション中またはアプリケーション セッションにまたがって、クライアント コンピューター上にアプリケーションによって格納される任意のデータです。 クッキー データは、通常、次の形式の名前と値のペアです。

<名前> = <>

データが、Cookie を設定する位置の Uri と共に SetCookie に渡されると、メモリ内に Cookie が作成され、現在のアプリケーション セッションの期間中のみ使用可能です。 この種類の Cookie は、"セッション Cookie" と呼ばれます。

複数のアプリケーション セッションにまたがってクッキーを格納するには、次の形式を使用して、有効期限をクッキーに追加する必要があります。

<名前> = <> ; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

有効期限を持つ Cookie は、Cookie の有効期限が切れるまで、現在の Windows インストールのインターネット一時ファイル フォルダーに格納されます。 このような Cookie は、アプリケーション セッションをまたいで存続するため、"永続的な Cookie" と呼ばれます。

セッション Cookie と永続的な Cookie の両方を取得するには、GetCookie メソッドを呼び出し、SetCookie メソッドで Cookie が設定された位置の Uri を渡します。

WPF で Cookie がどのようにサポートされるかを次に示します。

  • WPF スタンドアロン アプリケーションと XBAP では、Cookie の作成と管理の両方を行うことができます。

  • XBAP によって作成された Cookie には、ブラウザーからアクセスできます。

  • 同じドメインの XBAP は、Cookie を作成して共有できます。

  • 同じドメインの XBAP ページと HTML ページでは、Cookie を作成して共有できます。

  • XBAP ページと Loose XAML ページで Web 要求が行われると、Cookie がディスパッチされます。

  • 最上位の XBAP と IFRAMES でホストされる XBAP のどちらでも、Cookie にアクセスできます。

  • WPF での Cookie のサポートは、サポートされているすべてのブラウザーで同じです。

  • Internet Explorer では、WPF は、Cookie に関する P3P ポリシー (特に開発元とサードパーティの XBAP に関して) に従います。

構造化ナビゲーション

Page 間でデータを渡す必要がある場合、Page のパラメーターなしではないコンストラクターにデータを引数として渡すことができます。 この方法を使用する場合は、Page をキープ アライブ必要があることに注意してください。そうしなかった場合、次回、Page にナビゲートすると、WPF ではパラメーターなしのコンストラクターを使用して Page が再インスタンス化されます。

または、Page で、渡す必要のあるデータが設定されるプロパティを実装することができます。 ただし、Page でナビゲート元の Page にデータを渡す必要があるときは、少し手間がかかります。 問題は、ナビゲーションでは、ナビゲート後に Page に戻ることを保証するメカニズムがネイティブではサポートされていないことにあります。 基本的に、ナビゲーションは、"呼び出す/戻る" というセマンティクスをサポートしていません。 この問題を解決するため、WPF では、予測可能な構造化された方法で Page に戻ることを可能にする PageFunction<T> クラスが提供されています。 詳細については、「構造化ナビゲーションの概要」を参照してください。

NavigationWindow クラス

ここまでで、ナビゲート可能なコンテンツを含むアプリケーションをビルドするために使用する可能性が最も高いナビゲーション サービスの全容を説明しました。 これらのサービスについては、XBAP のコンテキストで説明しましたが、XBAP に限定されるわけではありません。 最新のオペレーティング システムと Windows アプリケーションでは、最近のユーザーがブラウザーの使用経験を持つことを考慮して、スタンドアロン アプリケーションにブラウザー スタイルのナビゲーションが組み込まれています。 一般的な例は、次のとおりです。

  • Word の類義語辞典: 単語の選択をナビゲートします。

  • エクスプローラー: ファイルとフォルダーをナビゲートします。

  • ウィザード: 複雑なタスクを複数のページに分割し、ページ間をナビゲートできます。 たとえば、Windows の機能の追加と削除を行う Windows コンポーネント ウィザードなどがあります。

ブラウザー スタイルのナビゲーションをスタンドアロン アプリケーションに組み込むには、NavigationWindow クラスを使用します。 NavigationWindow は、Window から派生し、XBAP で提供されるのと同様のナビゲーション サポートによってウィンドウを拡張します。 NavigationWindow は、スタンドアロン アプリケーションのメイン ウィンドウとして、またはダイアログ ボックスなどの 2 次ウィンドウとして使用できます。

NavigationWindow を実装するには、WPF の最上位クラス (WindowPage など) と同様に、マークアップとコードビハインドの組み合わせを使用します。 これを次の例に示します。

<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

このコードでは、NavigationWindow が開かれたときに自動的に Page (HomePage.xaml) にナビゲートする NavigationWindow を作成します。 NavigationWindow がアプリケーションのメイン ウィンドウの場合、StartupUri 属性を使用して起動できます。 これを次のマークアップに示します。

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

次の図では、スタンドアロン アプリケーションのメイン ウィンドウとしての NavigationWindow を示します。

メイン ウィンドウ

この図では、前の例の NavigationWindow 実装コードでは設定されなかったにもかかわらず、NavigationWindow にタイトルが表示されています。 代わりに、タイトルは、次のコードに示されている WindowTitle プロパティを使用して設定されます。

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

WindowWidth プロパティと WindowHeight プロパティの設定は、NavigationWindow にも影響します。

通常、動作や外観をカスタマイズする必要があるときには、独自の NavigationWindow を実装します。 どちらも行わない場合は、ショートカットを使用できます。 スタンドアロン アプリケーションで、Page のパック URI を StartupUri として指定した場合、Application では、Page をホストするための NavigationWindow が自動的に作成されます。 次のマークアップは、この方法を示しています。

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

ダイアログ ボックスなど、アプリケーションの 2 次ウィンドウを NavigationWindow にする場合は、次の例のコードを使用して開くことができます。

// 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()

次の図に、結果を示します。

ダイアログ ボックス

この図では、NavigationWindow に Internet Explorer スタイルの [戻る] ボタンと [進む] ボタンが表示され、ユーザーは履歴をナビゲートできます。 これらのボタンは、次の図に示されているように、同じユーザー エクスペリエンスを提供します。

NavigationWindow 内の [戻る] ボタンと [次に進む] ボタン

ページで独自の履歴ナビゲーション サポートと UI を提供する場合は、ShowsNavigationUI プロパティの値を false に設定することにより、NavigationWindow によって表示される [戻る] ボタンと [進む] ボタンを非表示にできます。

または、WPF のカスタマイズ サポートを使用して、NavigationWindow 自体の UI を置き換えることもできます。

Frame クラス

ブラウザーと NavigationWindow は両方とも、ナビゲート可能なコンテンツをホストするウィンドウです。 場合によっては、アプリケーションには、ウィンドウ全体でホストする必要のないコンテンツがあることもあります。 このようなコンテンツは、代わりに、他のコンテンツ内でホストされます。 Frame クラスを使用すると、ナビゲート可能なコンテンツを他のコンテンツに挿入することができます。 Frame では、NavigationWindow および XBAP と同じサポートが提供されます。

次の例では、Frame 要素を使用して FramePage に宣言によって追加する方法を示します。

<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>

このマークアップでは、Frame 要素の Source 属性に、Frame が最初にナビゲートする必要がある Page のパック URI を設定します。 次の図では、複数のページをナビゲートした Frame のある Page が含まれる XBAP を示します。

複数のページ間を移動したフレーム

Page のコンテンツの内部にある Frame のみを使用する必要はありません。 Window のコンテンツの内部で Frame をホストするのも一般的です。

既定の Frame では、別の履歴がない場合に限り、独自の履歴が使用されます。 FrameNavigationWindow または XBAP の内部でホストされるコンテンツの一部である場合、Frame では、NavigationWindow または XBAP に属する履歴が使用されます。 ただし、場合によっては、Frame では独自の履歴を使用しなければならないことがあります。 その理由の 1 つは、Frame によってホストされるページ内で履歴ナビゲーションを可能にすることです。 これを次の図に示します。

フレームとページのダイアグラム

この場合、FrameJournalOwnership プロパティを OwnsJournal に設定することによって、Frame が独自の履歴を使用するように構成できます。 これを次のマークアップに示します。

<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>

次の図は、独自の履歴を使用する Frame 内でのナビゲートの結果を示しています。

独自の履歴を使用するフレーム

履歴エントリは、Internet Explorer ではなく、Frame 内のナビゲーション UI によって表示されることに注意してください。

注意

FrameWindow でホストされるコンテンツの一部である場合、Frame では独自の履歴を使用するため、独自のナビゲーション UI が表示されます。

ユーザー エクスペリエンスで、Frame によってナビゲーション UI を表示せずに独自の履歴を表示する必要がある場合、NavigationUIVisibilityHidden に設定することにより、ナビゲーション UI を非表示にできます。 これを次のマークアップに示します。

<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>

FrameNavigationWindow は、ナビゲーション ホストと呼ばれるクラスです。 "ナビゲーション ホスト" は、コンテンツにナビゲートして表示できるクラスです。 これを実現するため、各ナビゲーション ホストでは、独自の NavigationService と履歴が使用されます。 ナビゲーション ホストの基本的な構造を次の図に示します。

ナビゲーターのダイアグラム

これにより、NavigationWindowFrame では、基本的に、XBAP がブラウザーでホストされるときに提供するのと同じナビゲーション サポートを提供できます。

NavigationService と履歴を使用するだけでなく、ナビゲーション ホストでは、NavigationService で実装されるのと同じメンバーが実装されます。 これを次の図に示します。

フレームおよび NavigationWindow 内の履歴

これにより、これらのメンバーに対して直接、ナビゲーション サポートをプログラミングできます。 Window でホストされる Frame のカスタム ナビゲーション UI を提供する必要がある場合は、この方法を検討してみてください。 さらに、どちらのタイプも、この他に、BackStack (NavigationWindow.BackStackFrame.BackStack) や ForwardStack (NavigationWindow.ForwardStackFrame.ForwardStack) など、ナビゲーション関連のメンバーを実装し、これらによって、それぞれ戻るスタックと進むスタックの履歴エントリを列挙できます。

前に述べたように、アプリケーション内に複数の履歴が存在することがあります。 次の図は、この例を示しています。

1 つのアプリケーション内の複数の履歴

このトピック全体を通じて、Page とパック XBAP を使用して、WPF のさまざまなナビゲーション機能を説明してきました。 ただし、アプリケーションにコンパイルされる Page がナビゲート可能な唯一の種類のコンテンツではなく、パック XBAP がコンテンツを識別する唯一の方法ではありません。

このセクションで示すように、Loose XAML ファイル、HTML ファイル、オブジェクトにもナビゲートできます。

Loose XAML ファイルとは、次の特性を持つファイルです。

  • XAML のみを含む (つまり、コードがない)。

  • 適切な名前空間宣言がある。

  • .xaml ファイル名拡張子を持つ。

たとえば、Loose XAML ファイル Person.xaml として格納されている次のようなコンテンツについて考えてみましょう。

<!-- 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>

ファイルをダブルクリックすると、ブラウザーが開き、コンテンツにナビゲートして、コンテンツを表示します。 これを次の図に示します。

Person.XAML ファイルの内容の表示

Loose XAML ファイルは、次の場所から表示できます。

  • ローカル コンピューター、イントラネット、またはインターネット上の Web サイト。

  • 汎用名前付け規則 (UNC) ファイル共有。

  • ローカル ディスク。

Loose XAML ファイルは、ブラウザーのお気に入りに追加したり、ブラウザーのホーム ページにしたりすることができます。

注意

Loose XAML ページの公開と起動の詳細については、「WPF アプリケーションを配置する」を参照してください。

Loose XAML に関する 1 つの制限は、部分信頼で実行しても安全なコンテンツしかホストできないことです。 たとえば、Window は、XAML ファイルのルート要素にはできません。 詳細については、「WPF 部分信頼セキュリティ」を参照してください。

ご想像のとおり、HTML にもナビゲートできます。 http スキームを使用する URI を入力するだけです。 たとえば、次の XAML は、HTML ページに移動する Frame を示しています。

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

HTML にナビゲートするには、特殊なアクセス許可が必要です。 たとえば、インターネット ゾーンの部分信頼セキュリティ サンドボックスで実行している XBAP からはナビゲートできません。 詳細については、「WPF 部分信頼セキュリティ」を参照してください。

WebBrowser コントロールでは、HTML ドキュメントのホスティング、ナビゲーション、およびスクリプトやマネージド コードの相互運用性がサポートされます。 WebBrowser コントロールの詳細については、「WebBrowser」を参照してください。

Frame と同様に、WebBrowser を使用して HTML にナビゲートするには、特殊なアクセス許可が必要です。 たとえば、部分信頼アプリケーションからは、起点サイトにある HTML にのみナビゲートできます。 詳細については、「WPF 部分信頼セキュリティ」を参照してください。

カスタム オブジェクトとして格納されているデータがある場合、そのデータを表示する方法の 1 つは、それらのオブジェクトにバインドされたコンテンツを使用して Page を作成することです (「データ バインドの概要」を参照)。 オブジェクトを表示するためだけにページ全体を作成するオーバーヘッドが必要ない場合には、代わりに、オブジェクトに直接ナビゲートすることもできます。

次のコードで実装される Person クラスを考えてみます。

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

それにナビゲートするには、次のコードに示されているように、NavigationWindow.Navigate メソッドを呼び出します。

<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

次の図に、結果を示します。

クラスに移動するページ

この図には、役立つものが何も表示されていません。 実際、表示される値は、Person オブジェクトの ToString メソッドの戻り値です。既定では、これは WPF でオブジェクトの表示に使用できる唯一の値です。 ToString メソッドをオーバーライドすると、より意味のある情報を返すことができますが、それでも文字列値でしかありません。 WPF の表示機能を利用する 1 つの方法は、データ テンプレートを使用することです。 WPF で特定の種類のオブジェクトと関連付けることができる、データ テンプレートを実装できます。 次のコードでは、Person オブジェクトのデータ テンプレートを示します。

<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>

ここでは、データ テンプレートは、DataType 属性で x:Type マークアップ拡張機能を使用することによって、Person 型と関連付けられます。 次に、データ テンプレートでは、TextBlock 要素 (TextBlock を参照) が Person クラスのプロパティにバインドされます。 次の図は、Person オブジェクトの更新された外観を示しています。

データ テンプレートを持つクラスへの移動

この方法の利点は、データ テンプレートを再利用して、アプリケーションの任意の場所で オブジェクトを一貫して表示できることによって得られる一貫性です。

データ テンプレートの詳細については「データ テンプレートの概要」を参照してください。

セキュリティ

WPF ナビゲーション サポートによって、XBAP をインターネットを介してナビゲートでき、アプリケーションでサード パーティの コンテンツをホストできます。 アプリケーションとユーザーの両方を有害な動作から保護するために、WPF では、さまざまなセキュリティ機能が提供されています。これらの機能の詳細は、「セキュリティ」と「WPF 部分信頼セキュリティ」で説明されています。

関連項目