다음을 통해 공유


구조적 탐색 개요

XAML browser application (XBAP), Frame 또는 NavigationWindow에서 호스팅될 수 있는 콘텐츠는 Pack uniform resource identifiers (URIs)로 식별되고 하이퍼링크를 통해 탐색 가능한 페이지로 구성됩니다. 페이지의 구조 및 하이퍼링크로 정의되는 페이지 탐색 방법을 탐색 토폴로지라고 합니다. 이러한 토폴로지는 다양한 종류의 응용 프로그램, 특히 문서를 탐색하는 응용 프로그램에 적합합니다. 이러한 응용 프로그램에서 사용자는 각 페이지에 대한 아무런 정보 없이 특정 페이지에서 다른 페이지를 탐색할 수 있습니다.

그러나 페이지에 탐색 시점 정보가 필요한 다른 종류의 응용 프로그램도 있습니다. 예를 들어 인사 관리 응용 프로그램에 회사의 모든 직원이 나열된 "직원 목록" 페이지가 있다고 가정해 보겠습니다. 이 페이지에서는 하이퍼링크를 클릭하여 새 직원을 추가할 수도 있습니다. 하이퍼링크를 클릭하면 "직원 추가" 페이지로 이동하여 새 직원에 대한 정보를 수집한 후 "직원 목록" 페이지로 돌아가 새 직원을 만들고 목록을 업데이트할 수 있습니다. 이러한 스타일의 탐색은 메서드를 호출하여 처리 작업을 수행한 후 값을 반환하는 구조적 프로그래밍과 유사합니다. 이러한 이유로 이러한 스타일의 탐색을 구조적 탐색이라고 합니다.

Page 클래스는 구조적 탐색을 지원하지 않습니다. 대신 Page에서 PageFunction<T> 클래스가 파생되어 구조적 탐색에 필요한 기본 생성자를 제공합니다. 이 항목에서는 PageFunction<T>을 사용하여 구조적 탐색을 설정하는 방법을 보여 줍니다.

이 항목에는 다음 단원이 포함되어 있습니다.

  • 구조적 탐색
  • PageFunction을 통한 구조적 탐색
  • 다른 종류의 구조적 탐색
  • 관련 항목

구조적 탐색

구조적 탐색에서 특정 페이지가 다른 페이지를 호출하는 경우 다음 동작의 일부 또는 전체가 수행되어야 합니다.

  • 호출 페이지가 호출 대상 페이지를 탐색하고, 호출 대상 페이지에 필요한 매개 변수를 선택적으로 전달합니다.

  • 호출 페이지를 사용하는 작업을 완료하면 호출 대상 페이지는 호출 페이지로 돌아가고 선택적으로 다음과 같은 작업을 수행합니다.

    • 호출 페이지가 완료된 방법을 설명하는 상태 정보를 반환합니다(예: 사용자가 OK 단추 또는 Cancel 단추를 눌렀는지 여부).

    • 사용자로부터 수집한 데이터를 반환합니다(예: 새 직원 정보).

  • 호출 페이지가 호출 대상 페이지로 돌아가면 호출 대상 페이지의 각 인스턴스를 구분하기 위해 호출 대상 페이지가 탐색 기록에서 제거됩니다.

다음 그림에서는 이러한 동작을 보여 줍니다.

호출 페이지와 호출된 페이지 사이의 흐름

PageFunction<T>을 호출 대상 페이지로 사용하여 이러한 동작을 구현할 수 있습니다.

PageFunction을 통한 구조적 탐색

이 항목에서는 PageFunction<T> 하나로 구성된 구조적 탐색의 기본 기술을 구현하는 방법을 보여 줍니다. 이 샘플에서 PagePageFunction<T>을 호출하여 사용자로부터 String 값을 받은 후 해당 값을 반환합니다.

호출 페이지 만들기

PageFunction<T>을 호출하는 페이지는 Page 또는 PageFunction<T>일 수 있습니다. 이 예제에서 호출 페이지는 다음 코드에 나와 있는 것과 같이 Page입니다.

<Page 
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="StructuredNavigationSample.CallingPage"
    WindowTitle="Calling Page" 
    WindowWidth="250" WindowHeight="150">


...


</Page>
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits Page
    Public Sub New()
        Me.InitializeComponent()


...


End Sub


...


End Class

End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {
        public CallingPage()
        {
            InitializeComponent();


...


}


...


    }
}

호출할 페이지 함수 만들기

호출 페이지는 호출 대상 페이지를 사용하여 사용자로부터 데이터를 수집하여 반환할 수 있기 때문에 PageFunction<T>은 제네릭 클래스로 구현되고, 이 클래스의 형식 인수는 호출 대상 페이지가 반환할 값의 형식을 지정합니다. 다음 코드에서는 PageFunction<T>을 사용하여 구현되고 String을 반환하는 호출 대상 페이지의 초기 구현을 보여 줍니다.

<PageFunction
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:sys="clr-namespace:System;assembly=mscorlib" 
    x:Class="StructuredNavigationSample.CalledPageFunction"
    x:TypeArguments="sys:String"
    Title="Page Function" 
    WindowWidth="250" WindowHeight="150">

  <Grid Margin="10">

    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto" />
      <RowDefinition />
    </Grid.RowDefinitions>

    <!-- Data -->
    <Label Grid.Column="0" Grid.Row="0">DataItem1:</Label>
    <TextBox Grid.Column="1" Grid.Row="0" Name="dataItem1TextBox"></TextBox>

    <!-- Accept/Cancel buttons -->
    <TextBlock Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right">
      <Button Name="okButton" IsDefault="True" MinWidth="50">OK</Button>
      <Button Name="cancelButton" IsCancel="True" MinWidth="50">Cancel</Button>
    </TextBlock>

  </Grid>

</PageFunction>
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of String)
    Public Sub New()
        Me.InitializeComponent()
    End Sub


...


End Class

End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {
        public CalledPageFunction()
        {
            InitializeComponent();
        }


...


    }
}

PageFunction<T> 선언은 형식 인수가 추가된다는 점을 제외하고는 Page 선언과 유사합니다. 코드 예제에서 알 수 있듯이 형식 인수는 x:TypeArguments 특성을 사용하여 XAML 태그에도 지정되고, 표준 제네릭 형식 인수 구문을 사용하여 숨김 코드에도 지정됩니다.

.NET Framework 클래스만 형식 인수로 사용할 수 있는 것은 아닙니다. PageFunction<T>을 호출하여 사용자 지정 형식으로 추상화된 도메인별 데이터를 수집할 수도 있습니다. 다음 코드에서는 사용자 지정 형식을 PageFunction<T>의 형식 인수로 사용하는 방법을 보여 줍니다.

Public Class CustomType


...


End Class
namespace SDKSample
{
    public class CustomType
    {


...


    }
}
<PageFunction
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SDKSample" 
    x:Class="SDKSample.CustomTypePageFunction"
    x:TypeArguments="local:CustomType">


...


</PageFunction>
Partial Public Class CustomTypePageFunction
    Inherits System.Windows.Navigation.PageFunction(Of CustomType)
using System.Windows.Navigation; // PageFunction

namespace SDKSample
{
    public partial class CustomTypePageFunction : PageFunction<CustomType>
    {

PageFunction<T>의 형식 인수는 호출 페이지와 호출 대상 페이지 사이의 통신 기반을 제공합니다. 자세한 내용은 다음 단원에서 설명합니다.

다음 단원에서 설명하겠지만 PageFunction<T> 선언을 통해 식별되는 형식은 PageFunction<T>에서 호출 페이지로 데이터를 반환하는 데 매우 중요한 역할을 합니다.

PageFunction 호출 및 매개 변수 전달

페이지를 호출하려면 호출 페이지는 호출 대상 페이지를 인스턴스화하고 Navigate 메서드를 사용하여 해당 페이지를 탐색해야 합니다. 이렇게 하면 호출 페이지는 호출 대상 페이지에 초기 데이터(예: 호출 대상 페이지에서 수집하는 데이터의 기본값)를 전달할 수 있습니다.

다음 코드에서는 호출 페이지에서 전달된 매개 변수를 받으며 기본이 아닌 생성자를 사용하는 호출 대상 페이지를 보여 줍니다.

Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of String)


...


Public Sub New(ByVal initialDataItem1Value As String)
    Me.InitializeComponent()


...


    ' Set initial value
    Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub


...


End Class

End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {


...


        public CalledPageFunction(string initialDataItem1Value)
        {
            InitializeComponent();



...


    // Set initial value
    this.dataItem1TextBox.Text = initialDataItem1Value;
}


...


    }
}

다음 코드에서는 호출 대상 페이지를 인스턴스화하고 초기 문자열 값을 이 페이지에 전달하기 위해 HyperlinkClick 이벤트를 처리하는 호출 페이지를 보여 줍니다.

Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits Page
    Public Sub New()
        Me.InitializeComponent()
        AddHandler Me.pageFunctionHyperlink.Click, New RoutedEventHandler(AddressOf Me.pageFunctionHyperlink_Click)
    End Sub
    Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)


...


End Sub


...


End Class

End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {
        public CallingPage()
        {
            InitializeComponent();
            this.pageFunctionHyperlink.Click += new RoutedEventHandler(pageFunctionHyperlink_Click);
        }
        void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
        {

            // Instantiate and navigate to page function
            CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");


...


}


...


    }
}
<Hyperlink Name="pageFunctionHyperlink">Call Page Function</Hyperlink>

호출 대상 페이지에 매개 변수를 전달하는 대신 다음과 같이 할 수 있습니다.

  • 호출 페이지에서 다음을 수행합니다.

    1. 기본 생성자를 사용하여 호출 대상 PageFunction<T>을 인스턴스화합니다.

    2. 매개 변수를 Properties에 저장합니다.

    3. 호출 대상 PageFunction<T>을 탐색합니다.

  • 호출 대상 PageFunction<T>에서 다음을 수행합니다.

    • Properties에 저장된 매개 변수를 검색하고 사용합니다.

잠시 후에 설명하겠지만 호출 대상 페이지에서 반환하는 데이터를 수집하려면 여전히 코드를 사용하여 호출 대상 페이지를 인스턴스화하고 탐색해야 합니다. 이러한 이유 때문에 PageFunction<T>을 유지해야 합니다. 그렇지 않으면 다음에 PageFunction<T>을 탐색할 때 WPF에서 기본 생성자를 사용하여 PageFunction<T>을 인스턴스화합니다.

그러나 호출 대상 페이지가 돌아가려면 호출 페이지에서 검색할 수 있는 데이터를 반환해야 합니다.

호출 페이지로 작업 결과 및 작업 데이터 반환

사용자가 호출 대상 페이지 사용을 마치면 호출 대상 페이지가 돌아가야 합니다. 이 예제에서는 OK 또는 Cancel 단추를 눌러 호출 대상 페이지 사용을 마쳤는지 알릴 수 있습니다. 호출 페이지는 호출 대상 페이지를 사용하여 사용자로부터 데이터를 수집했기 때문에 호출 페이지에는 두 가지 종류의 정보가 필요합니다.

  1. 호출 대상 페이지를 취소했는지 여부. 이 예제에서는 OK 단추 또는 Cancel 단추를 눌러 호출 대상 페이지에서 수행한 작업을 취소하거나 승인할 수 있습니다. 이 정보를 통해 호출 페이지는 사용자로부터 수집한 데이터를 처리해야 할지 여부를 결정할 수 있습니다.

  2. 사용자가 제공한 데이터

PageFunction<T>OnReturn 메서드를 구현하여 정보를 반환합니다. 다음 코드에서는 이 메서드를 호출하는 방법을 보여 줍니다.

Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of String)


...


    Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' Accept when Ok button is clicked
        Me.OnReturn(New ReturnEventArgs(Of String)(Me.dataItem1TextBox.Text))
    End Sub

    Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' Cancel
        Me.OnReturn(Nothing)
    End Sub
End Class

End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {


...


        void okButton_Click(object sender, RoutedEventArgs e)
        {
            // Accept when Ok button is clicked
            OnReturn(new ReturnEventArgs<string>(this.dataItem1TextBox.Text));
        }

        void cancelButton_Click(object sender, RoutedEventArgs e)
        {
            // Cancel 
            OnReturn(null);
        }
    }
}

이 예제의 경우 사용자가 Cancel 단추를 누르면 호출 페이지에 null 값이 반환되고, OK 단추를 누르면 사용자가 입력한 문자열 값이 반환됩니다. OnReturn은 데이터를 호출 페이지에 반환하기 위해 호출하는 protected virtual 메서드입니다. 데이터는 Result의 반환 값 형식을 지정하는 형식 인수가 포함된 제네릭 ReturnEventArgs<T> 형식의 인스턴스에 패키지되어야 합니다. 이렇게 할 경우 특정 형식 인수를 사용하여 PageFunction<T>을 선언하면 PageFunction<T>에서 해당 형식 인수로 지정된 형식의 인스턴스를 반환합니다. 이 예제에서는 형식 인수 및 반환 값의 형식이 String입니다.

OnReturn을 호출하면 호출 페이지가 PageFunction<T>의 반환 값을 어떤 방법으로든 검색해야 합니다. 이러한 이유로 PageFunction<T>은 호출 페이지에서 처리할 Return 이벤트를 구현합니다. OnReturn을 호출하면 Return이 발생하여 호출 페이지가 알림을 받도록 Return에 등록할 수 있습니다.

Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits Page


...


    Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' Instantiate and navigate to page function
        Dim calledPageFunction As New CalledPageFunction("Initial Data Item Value")
        AddHandler calledPageFunction.Return, New ReturnEventHandler(Of String)(AddressOf Me.calledPageFunction_Return)
        MyBase.NavigationService.Navigate(calledPageFunction)
    End Sub
    Private Sub calledPageFunction_Return(ByVal sender As Object, ByVal e As ReturnEventArgs(Of String))

        Me.pageFunctionResultsTextBlock.Visibility = Windows.Visibility.Visible

        ' Display result
        Me.pageFunctionResultsTextBlock.Text = IIf((Not e Is Nothing), "Accepted", "Canceled")

        ' If page function returned, display result and data
        If (Not e Is Nothing) Then
            Me.pageFunctionResultsTextBlock.Text = (Me.pageFunctionResultsTextBlock.Text & ChrW(10) & e.Result)
        End If

    End Sub
End Class

End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {


...


        void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
        {

            // Instantiate and navigate to page function
            CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");
            CalledPageFunction.Return += pageFunction_Return;
            this.NavigationService.Navigate(CalledPageFunction);
        }
        void pageFunction_Return(object sender, ReturnEventArgs<string> e)
        {
            this.pageFunctionResultsTextBlock.Visibility = Visibility.Visible;

            // Display result
            this.pageFunctionResultsTextBlock.Text = (e != null ? "Accepted" : "Canceled");

            // If page function returned, display result and data
            if (e != null)
            {
                this.pageFunctionResultsTextBlock.Text += "\n" + e.Result;
            }
        }
    }
}

작업 완료 시 작업 페이지 제거

호출 대상 페이지가 돌아가는 경우 사용자가 호출 대상 페이지를 취소하지 않았으면 호출 페이지가 사용자가 제공하고 호출 대상 페이지에서 반환한 데이터를 처리합니다. 일반적으로 이러한 방식의 데이터 수집은 격리된 작업입니다. 따라서 호출 대상 페이지가 돌아가면 호출 페이지에서는 더 많은 데이터를 캡처하기 위해 새 호출 페이지를 만들고 탐색해야 합니다.

그러나 호출 대상 페이지를 저널에서 제거하지 않으면 사용자가 호출 페이지의 이전 인스턴스를 다시 탐색할 수 있습니다. PageFunction<T>을 저널에 유지할지 여부는 RemoveFromJournal 속성을 통해 결정됩니다. RemoveFromJournal은 기본적으로 true로 설정되기 때문에 페이지 함수는 OnReturn이 호출되면 자동으로 제거됩니다. OnReturn이 호출된 이후에도 탐색 기록에 페이지 함수를 유지하려면 RemoveFromJournal을 false로 설정해야 합니다.

다른 종류의 구조적 탐색

이 항목에서는 호출/반환 구조적 탐색을 지원하는 가장 기본적인 PageFunction<T> 사용 방법에 대해 설명합니다. 이를 기초로 하여 복잡한 형식의 구조적 탐색을 만들 수 있습니다.

예를 들어 호출 페이지에서 사용자로부터 충분한 데이터를 수집하거나 작업을 수행하기 위해 여러 페이지를 사용해야 하는 경우도 있습니다. 이와 같이 여러 페이지를 사용하는 경우를 "마법사"라고 합니다.

응용 프로그램의 탐색 토폴로지가 복잡하여 구조적 탐색을 사용해야만 응용 프로그램이 효과적으로 작동하는 경우도 있습니다. 자세한 내용은 탐색 토폴로지 개요를 참조하십시오.

참고 항목

참조

PageFunction<T>

NavigationService

개념

탐색 토폴로지 개요