탐색 개요

WPF(Windows Presentation Foundation)는 독립 실행형 애플리케이션과 XBAP(XAML 브라우저 애플리케이션)라는 두 유형의 애플리케이션에서 사용할 수 있는 브라우저 스타일 탐색을 제공합니다. 탐색을 위한 콘텐츠를 패키징할 수 있도록 WPF는 Page 클래스를 제공합니다. Hyperlink를 사용하여 선언적으로 또는 NavigationService를 사용하여 프로그래밍 방식으로 Page 간에 탐색할 수 있습니다. WPF는 저널을 사용하여 탐색했던 페이지를 기억했다가 다시 해당 페이지로 돌아옵니다.

Page, Hyperlink, NavigationService 및 저널은 WPF에서 제공하는 탐색 지원의 핵심을 형성합니다. 이 개요에서는 이러한 기능을 자세히 알아본 후 사용 완화 XAML(Extensible Application Markup Language), 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는 하나의 자식 요소만 포함할 수 있습니다. 앞의 예제에서 콘텐츠는 단일 문자열 "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가 있으면 MSBuild(Microsoft Build Engine)에서는 Page에서 파생되며 x:Class 특성에 의해 이름이 지정되는 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 클래스는 필수 애플리케이션 인프라를 설정하는 애플리케이션 정의의 일부입니다(애플리케이션 관리 개요 참조).

애플리케이션 정의는 일반적으로 MSBuildApplicationDefinition 항목으로 구성된 태그 파일과 함께 태그와 코드 숨김을 사용하여 구현됩니다. 다음은 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는 애플리케이션 정의를 사용하여 XBAP 시작 시 자동으로 로드되는 Page인 시작 Page를 지정할 수 있습니다. 이 작업은 원하는 Page에 대한 URI(Uniform Resource Identifier)를 사용하여 StartupUri 속성을 설정하는 방법으로 수행합니다.

참고

대부분의 경우 Page는 애플리케이션으로 컴파일되거나 애플리케이션과 함께 배포됩니다. 이 경우 Page를 식별하는 URI는 구성표를 준수하는 URI인 Pack URI입니다. Pack URI는 WPF의 Pack 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을 식별하는 상대적 Pack URI를 사용하여 설정됩니다. XBAP가 시작되면 HomePage.xaml이 자동으로 탐색되고 표시됩니다. 다음 그림은 웹 서버에서 실행된 XBAP를 보여줍니다.

XBAP 페이지

참고

XBAP 개발 및 배포에 대한 자세한 내용은 WPF XAML 브라우저 애플리케이션 개요WPF 애플리케이션 배포를 참조하세요.

호스트 창 제목, 너비 및 높이 구성

앞의 그림에서 알 수 있듯이 브라우저와 탭 패널의 제목은 XBAP의 URI입니다. 이 제목은 길이가 길며 모양이나 정보 제공 측면 모두에서 그다지 유용하지 않습니다. 이러한 이유로 PageWindowTitle 속성을 설정하여 제목을 변경할 수 있는 방법을 제공합니다. 또한 WindowWidthWindowHeight를 각각 설정하여 브라우저 창의 너비와 높이를 구성할 수 있습니다.

다음 예제처럼 태그에서 선언적으로 WindowTitle, WindowWidthWindowHeight를 설정할 수 있습니다.

<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 요소를 사용하여 PageHyperlink를 선언적으로 추가할 수 있습니다.

<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의 Pack URI

  • 사용자가 클릭하여 텍스트 및 이미지 등의 탐색을 시작할 수 있는 콘텐츠(Hyperlink 요소에 포함될 수 있는 콘텐츠는 Hyperlink 참조)

다음 그림에서는 Hyperlink가 있는 Page가 포함된 XBAP를 보여줍니다.

하이퍼링크가 있는 페이지

예상한 대로 Hyperlink를 클릭하면 XBAP가 NavigateUri 특성에서 식별한 Page로 이동합니다. 또한 XBAP는 Internet Explorer의 최근 페이지 목록에 이전 Page에 대한 항목을 추가합니다. 다음 그림에서 이를 확인할 수 있습니다.

뒤로 및 앞으로 단추

HyperlinkPage 간의 탐색뿐 아니라 조각 탐색도 지원합니다.

조각 탐색

조각 탐색은 현재 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를 통해 페이지를 찾을 수 있는 경우에만 XAML 사용 완화 페이지(루트 요소가 Page인 태그 전용 XAML 파일)에서 조각을 탐색할 수 있습니다.

그러나 XAML 사용 완화 페이지에서 자체 조각을 탐색할 수 있습니다.

Hyperlink를 사용하면 사용자가 특정 Page로의 탐색을 시작할 수 있지만 페이지 찾기 및 다운로드 작업은 NavigationService 클래스에 의해 수행됩니다. 기본적으로 NavigationServiceHyperlink처럼 클라이언트 코드를 대신하여 탐색 요청을 처리하는 기능을 제공합니다. 또한 NavigationService는 탐색 요청을 추적하고 이에 영향을 주는 높은 수준의 지원을 구현합니다.

Hyperlink를 클릭하면 WPF가 Page를 호출하여 지정된 Pack URI에 있는 NavigationService.Navigate를 찾아서 다운로드합니다. 다운로드된 Page는 루트 개체가 다운로드된 Page의 인스턴스인 개체 트리로 변환됩니다. 루트 Page 개체에 대한 참조는 NavigationService.Content 속성에 저장됩니다. 탐색된 콘텐츠의 Pack URI는 NavigationService.Source 속성에 저장되고, 탐색된 마지막 페이지의 Pack URI는 NavigationService.CurrentSource에 저장됩니다.

참고

WPF 애플리케이션에는 현재 활성 상태인 NavigationService가 둘 이상 있을 수 있습니다. 자세한 내용은 이 항목 뒷부분의 탐색 호스트를 참조하세요.

탐색 서비스를 사용하여 프로그래밍 방식으로 탐색

태그에서 Hyperlink를 사용하여 탐색이 선언적으로 구현된 경우 사용자 대신 HyperlinkNavigationService를 사용하므로 NavigationService에 대해 알 필요가 없습니다. 즉, Hyperlink의 직접 또는 간접 부모가 탐색 호스트(탐색 호스트 참조)인 경우 Hyperlink는 탐색 호스트의 탐색 서비스를 찾아 사용하여 탐색 요청을 처리할 수 있습니다.

그러나 다음과 같이 NavigationService를 직접 사용해야 할 때가 있습니다.

  • 매개 변수가 없는 생성자가 아닌 생성자를 사용하여 Page를 인스턴스화해야 하는 경우

  • 탐색하기 전에 Page의 속성을 설정해야 하는 경우

  • 탐색해야 하는 Page를 런타임에만 결정할 수 있는 경우

이러한 경우에는 NavigationService 개체의 Navigate 메서드를 호출하여 프로그래밍 방식으로 탐색을 시작하는 코드를 작성해야 합니다. 이를 위해서는 NavigationService에 대한 참조가 필요합니다.

NavigationService에 대한 참조 가져오기

탐색 호스트 섹션에 설명된 이유로 인해 WPF 애플리케이션에 둘 이상의 NavigationService가 있을 수 있습니다. 즉, 코드에 NavigationService를 찾는 방법이 필요하며, 보통은 현재 Page를 탐색한 NavigationService입니다. staticNavigationService.GetNavigationService 메서드를 호출하여 NavigationService에 대한 참조를 가져올 수 있습니다. 특정 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를 신속하게 찾을 수 있도록 PageNavigationService 속성을 구현합니다. 다음 예제에서 이를 확인할 수 있습니다.

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에 대한 참조만 가져올 수 있습니다.

프로그래밍 방식으로 Page 개체 탐색

다음 예제에서는 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

PageHyperlink를 클릭하면 매개 변수 없는 생성자가 아닌 생성자를 사용하여 탐색할 Page가 인스턴스화되고 NavigationService.Navigate 메서드를 호출하여 탐색이 시작됩니다. Navigate는 Pack URI가 아닌 NavigationService가 탐색할 개체에 대한 참조를 사용합니다.

Pack URI를 사용하여 프로그래밍 방식으로 탐색

프로그래밍 방식으로 Pack URI를 생성해야 하는 경우(예: 런타임에만 Pack 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

현재 페이지 새로 고침

NavigationService.Source 속성에 저장된 Pack URI와 동일한 Pack URI가 있는 경우 Page가 다운로드되지 않습니다. 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가 이러한 이벤트에 관심이 있는 경우도 있습니다. 예를 들어 PageNavigationService.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는 두 개의 스택(뒤로 스택 및 앞으로 스택)을 사용하여 탐색한 페이지를 기억합니다. 현재 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에서 제공하는 선언적 및 프로그래밍 방식의 메커니즘을 사용하여 저널을 탐색할 수도 있습니다. 이를 수행하는 이유 중 한 가지는 페이지에 사용자 지정 탐색 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 인스턴스를 유지해야 하는 경우 두 가지 기술을 사용하여 이를 수행할 수 있습니다. 먼저 NavigationService.Navigate 메서드를 호출하여 프로그래밍 방식으로 Page 개체를 탐색할 수 있습니다.

둘째, 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의 인스턴스는 저널에 유지되므로 저널에 남아 있는 한 다시 인스턴스화되지 않습니다. 결과적으로 PagePage를 탐색할 때마다 호출되어야 하는 초기화 논리가 있는 경우 생성자에서 Loaded 이벤트에 대한 처리기로 이를 이동해야 합니다. 다음 그림과 같이 LoadedUnloaded 이벤트는 각각 Page 간에 탐색할 때마다 발생합니다.

로드 및 언로드된 이벤트가 발생하는 경우

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가 탐색됩니다.

WPF는 Page에서 다음 컨트롤이 사용될 때 이 지원을 자동으로 사용합니다.

Page에서 이러한 컨트롤을 사용하면 여기에 입력된 데이터는 다음 그림의 Favorite ColorListBox와 같이 Page 탐색 간에 기억됩니다.

기억 상태인 컨트롤이 있는 페이지

Page에 위의 목록 이외의 컨트롤이 있거나 상태가 사용자 지정 개체에 저장되어 있는 경우 Page 탐색 중 저널에서 상태를 기억하도록 코드를 작성해야 합니다.

Page 탐색 중 작은 상태 조각을 기억해야 할 경우 FrameworkPropertyMetadata.Journal 메타데이터 플래그로 구성된 종속성 속성(DependencyProperty)을 사용할 수 있습니다.

탐색 중 Page에서 기억해야 할 상태가 여러 데이터 조각으로 이루어진 경우 단일 클래스에서 상태를 캡슐화하고 IProvideCustomContentState 인터페이스를 구현하는 데 집중적으로 코드를 사용하지 않을 수도 있습니다.

단일 Page의 다양한 상태를 탐색해야 할 경우 Page 자체에서 탐색하지 않고 IProvideCustomContentStateNavigationService.AddBackEntry를 사용하면 됩니다.

쿠키

WPF 애플리케이션에서 데이터를 저장할 수 있는 또 다른 방법은 SetCookieGetCookie 메서드를 사용하여 생성, 업데이트 및 삭제할 수 있는 쿠키입니다. WPF에서 만들 수 있는 쿠키는 다른 유형의 웹 애플리케이션이 사용하는 쿠키와 같습니다. 쿠키는 애플리케이션 세션 동안 또는 애플리케이션 세션 간에 클라이언트 컴퓨터의 애플리케이션에 저장되는 임의의 데이터 조각입니다. 쿠키 데이터는 일반적으로 다음과 같은 이름/값 쌍 형식을 사용합니다.

이름=

쿠키를 설정해야 하는 위치의 Uri와 함께 데이터를 SetCookie에 전달하면 쿠키가 메모리 내에 만들어지며, 현재 애플리케이션 세션에서만 사용할 수 있습니다. 이러한 종류의 쿠키를 세션 쿠키라고 합니다.

애플리케이션 세션 간에 쿠키를 저장하려면 다음 형식을 사용하여 쿠키에 만료 날짜를 추가해야 합니다.

이름=; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

만료 날짜가 있는 쿠키는 쿠키가 만료될 때까지 현재 Windows 설치의 Temporary Internet Files 폴더에 저장됩니다. 이러한 쿠키는 애플리케이션 세션 간에 유지되므로 영구적 쿠키라고 합니다.

GetCookie 메서드를 호출하고, 쿠키가 설정된 위치의 UriSetCookie 메서드와 함께 전달하여 세션 쿠키 및 영구적 쿠키를 검색합니다.

다음은 WPF에서 쿠키를 지원하는 몇 가지 방법입니다.

  • WPF 독립 실행형 애플리케이션 및 XBAP는 모두 쿠키를 만들고 관리합니다.

  • XBAP에서 만들어진 쿠키를 브라우저에서 액세스할 수 있습니다.

  • 동일한 도메인의 XBAP에서 쿠키를 만들고 공유할 수 있습니다.

  • 동일한 도메인의 XBAP 및 HTML 페이지에서 쿠키를 만들고 공유할 수 있습니다.

  • XBAP 및 XAML 사용 완화 페이지가 웹 요청을 만들 때 쿠키가 디스패치됩니다.

  • 최상위 수준 XBAP 및 IFRAMES에 호스트되는 XBAP에서 쿠키에 액세스할 수 있습니다.

  • WPF의 쿠키 지원은 지원되는 모든 브라우저에서 동일합니다.

  • Internet Explorer에서 쿠키와 관련된 P3P 정책은 특히 자사 및 타사 XBAP와 관련하여 WPF에 의해 적용됩니다.

구조적 탐색

Page 간에 데이터를 전달해야 하는 경우 Page의 매개 변수 없는 생성자가 아닌 생성자의 인수로 데이터를 전달할 수 있습니다. 이 기술을 사용하는 경우 Page를 활성 상태로 유지해야 합니다. 그러지 않으면 다음에 Page를 탐색할 때 WPF가 매개 변수 없는 생성자를 사용하여 Page를 다시 인스턴스화합니다.

또는 Page가 전달해야 하는 데이터로 설정된 속성을 구현할 수 있습니다. 그러나 Page가 탐색한 Page에 데이터를 다시 전달해야 하는 경우 상황이 까다로워집니다. 문제는 탐색 후 Page가 반환되도록 하는 메커니즘을 기본적으로 지원하지 않는다는 것입니다. 기본적으로 탐색은 호출/반환 의미 체계를 지원하지 않습니다. 이 문제를 해결하기 위해 WPF에서는 Page가 예측 가능하고 구조화된 방식으로 반환되도록 보장하는 데 사용할 수 있는 PageFunction<T> 클래스를 제공합니다. 자세한 내용은 구조적 탐색 개요를 참조하세요.

NavigationWindow 클래스

지금까지 탐색 가능한 콘텐츠로 애플리케이션을 빌드하는 데 가장 많이 사용되는 탐색 서비스 영역을 살펴보았습니다. 이러한 서비스는 XBAP 컨텍스트에서 설명했지만, XBAP로 국한되지 않습니다. 최신 운영 체제 및 Windows 애플리케이션은 현대 사용자의 브라우저 경험을 활용하여 브라우저 스타일 탐색을 독립 실행형 애플리케이션에 통합합니다. 일반적인 예제는 다음을 포함합니다.

  • 단어 동의어 사전: 선택한 단어를 탐색합니다.

  • 파일 탐색기: 파일 및 폴더를 탐색합니다.

  • 마법사: 복잡한 작업을 여러 페이지로 나누어 탐색할 수 있습니다. Windows 기능의 추가 및 제거를 처리하는 Windows 구성 요소 마법사를 예로 들 수 있습니다.

독립 실행형 애플리케이션에 브라우저 스타일 탐색을 통합하려면 NavigationWindow 클래스를 사용하면 됩니다. NavigationWindowWindow에서 파생되고 XBAP가 제공하는 탐색에 대한 동일한 지원으로 확장됩니다. NavigationWindow는 독립 실행형 애플리케이션의 주 창이나 대화 상자와 같은 보조 창으로 사용할 수 있습니다.

대부분의 WPF 최상위 클래스(Window, Page 등)와 마찬가지로 NavigationWindow를 구현하려면 태그와 코드 숨김의 조합을 사용합니다. 다음 예제에서 이를 확인할 수 있습니다.

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

WindowWidthWindowHeight 속성을 설정하면 NavigationWindow에도 영향을 줍니다.

일반적으로 동작 또는 모양을 사용자 지정해야 하는 경우 직접 NavigationWindow를 구현합니다. 두 방법을 모두 사용하지 않으려면 바로 가기를 사용할 수 있습니다. 독립 실행형 애플리케이션에서 Page의 Pack URI를 StartupUri로 지정하면 Application에서 Page를 호스트할 NavigationWindow를 자동으로 만듭니다. 다음 태그에서는 이 기능을 설정하는 방법을 보여 줍니다.

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

대화 상자와 같은 보조 애플리케이션 창을 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 클래스를 사용하여 탐색 가능한 콘텐츠를 다른 콘텐츠에 삽입할 수 있습니다. FrameNavigationWindow 및 XBAP와 동일한 지원을 제공합니다.

다음 예제에서는 Frame 요소를 사용하여 Frame을 선언적으로 Page에 추가하는 방법을 보여줍니다.

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

이 태그는 Pack URI를 사용하여 Frame이 처음 이동해야 하는 Page에 대한 Frame 요소의 Source 특성을 설정합니다. 다음 그림에서는 여러 페이지 사이를 탐색한 Frame이 있는 Page가 포함된 XBAP를 보여줍니다.

여러 페이지 간을 탐색한 프레임

Page 콘텐츠 내에서 Frame만 사용할 필요가 없습니다. 또한 Window 콘텐츠 내에서 Frame을 호스트하는 것이 일반적입니다.

기본적으로 Frame은 다른 저널이 없는 경우에만 자체 저널을 사용합니다. FrameNavigationWindow 또는 XBAP 내부에서 호스트되는 콘텐츠의 일부인 경우 FrameNavigationWindow 또는 XBAP에 속한 저널을 사용합니다. 그러나 때로는 Frame이 자체 저널을 담당해야 할 수도 있습니다. 그 이유 중 하나는 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를 표시합니다.

사용자 환경에서 탐색 UI를 표시하지 않고 Frame이 자체 저널을 제공해야 하는 경우 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가 구현하는 것과 동일한 멤버를 구현합니다. 다음 그림에서 이를 확인할 수 있습니다.

Frame 및 NavigationWindow의 저널

이를 통해 직접 탐색 지원을 프로그래밍할 수 있습니다. Window에 호스트되는 Frame에 대해 사용자 지정 탐색 UI를 제공해야 하는 경우 이를 고려할 수 있습니다. 또한 두 유형 모두 BackStack(NavigationWindow.BackStack, Frame.BackStack) 및 ForwardStack(NavigationWindow.ForwardStack, Frame.ForwardStack)을 포함한 탐색 관련 멤버를 추가로 구현합니다. 이러한 멤버를 사용하면 각각 뒤로 스택과 앞으로 스택의 저널 항목을 열거할 수 있습니다.

앞서 언급했듯이 애플리케이션에는 둘 이상의 저널이 있을 수 있습니다. 다음 그림은 이러한 상황이 발생할 수 있는 예제를 제공합니다.

한 애플리케이션 이내 여러 저널

이 토픽에서는 WPF의 다양한 탐색 기능을 보여주기 위해 Page 및 Pack XBAP를 사용했습니다. 그러나 애플리케이션으로 컴파일되는 Page가 탐색할 수 있는 유일한 콘텐츠 형식은 아니며 Pack XBAP가 콘텐츠를 식별하는 유일한 방법도 아닙니다.

이 섹션에서 설명하는 것처럼 XAML 사용 완화 파일, HTML 파일 및 개체를 탐색할 수도 있습니다.

XAML 사용 완화 파일은 다음과 같은 특징을 가진 파일입니다.

  • XAML만 포함합니다(즉, 코드 없음).

  • 적절한 네임스페이스 선언이 있습니다.

  • .xaml 파일 이름 확장명이 있습니다.

예를 들어 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 파일의 콘텐츠 표시

다음에서 XAML 사용 완화 파일을 표시할 수 있습니다.

  • 로컬 컴퓨터, 인트라넷 또는 인터넷의 웹 사이트

  • UNC(범용 명명 규칙) 파일 공유입니다.

  • 로컬 디스크

XAML 사용 완화 파일을 브라우저의 즐겨찾기에 추가하거나 브라우저의 홈페이지로 만들 수 있습니다.

참고

XAML 사용 완화 페이지를 게시하고 시작하는 방법에 대한 자세한 내용은 WPF 애플리케이션 배포를 참조하세요.

XAML 사용 완화 파일과 관련된 한 가지 제한 사항은 부분 신뢰로 실행하기에 안전한 콘텐츠만 호스트할 수 있다는 것입니다. 예를 들어 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 부분 신뢰 보안을 참조하세요.

사용자 지정 개체로 저장된 데이터가 있는 경우 데이터를 표시하는 한 가지 방법은 해당 개체에 바인딩된 콘텐츠를 사용하여 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의 프레젠테이션 기능을 이용하는 한 가지 기술은 데이터 템플릿을 사용하는 것입니다. 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 부분 신뢰 보안에 설명된 다양한 보안 기능을 제공합니다.

참고 항목