본문 바로가기

IT 살이/04. 기술 - 프로그래밍

12 PageFunction

이 포스트는 MSDN 메거진에 실린 아티클을 번역한 글의 일부이다.


이처럼 컨텐트가 다양한 곳에서 올 수 있고, 하이퍼링크 기반의 애플리케이션에서는 다른 어떤 곳으로의 네비게이션을 허락하기 때문에 어떤 태스크를 완수하기가 어려워질 수 있다. 하이퍼링크 기반의 애플리케이션은 사용자들을 특정 페이지에 국한시키는 것이 쉬운 문제가 아니기 때문이다. 애플리케이션이 하이퍼링크를 제공하는가 여부에 상관없이 사용자들은 브라우저의 주소창을 이용해서 어떤 페이지로든지 이동할 수 있다. 결과적으로 사용자는 아직 태스크가 완료되지 않은 상태에서 태스크를 시작했던 페이지를 떠나버릴 수 있다. Web에서는 세션 상태 등을 이용해서 다이얼 로그 창 스타일을 만들어 낼 수 있는 많은 트릭이 있지만 불행히도 많은 부하가 걸리는 작업이다. 다이얼 로그 창이 문제를 해결할 수 있는 방법이긴 하지만 보안과 관련된 이유로 해서 XBAP과 같은 애플리케이션은 윈도우를 만들어 낼 수 없다. 이것은 기본적으로 Internet Zone의 부분 신뢰의 환경에서 구동된다.

다행히 WPF는 페이지 펑크션(page function)으로 모달창 스타일의 일 처리를 대체할 수 있다. 이것은 제너릭 타입 PageFuntion으로 구현되는데, Page에서 직접 상속을 받는다. 결과적으로 PageFunction Page처럼 보이고 다음과 같은 방식으로 쉽게 만들 수 있다.

<!--OrderABoxPageFunction.xaml (markup) -->

<PageFunction

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

  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

  xmlns:local="clr-namespace:BoxApplicationXBAP"

  x:Class="BoxApplicationXBAP.OrderABoxPageFunction"

  x:TypeArguments="local:Order"

  WindowTitle="Box Application - Order a Box" >

  ...

  <!--Content-->   

  ...

<PageFunction>

// OrderABoxPageFunction.cs (code-behind)

public partial class OrderABoxPageFunction:

  PageFunction<Order> { ... }

이 페이지 펑크션의 예제는 Order로 구현된 주문 정보를 모으는 일을 한다. 태스크는 주로 이렇게 데이터를 대상으로 해서 수행되므로 PageFunction은 태스크가 수행될 데이터의 특정 타입을 x:TypeArguments 어트리뷰트를 이용해서 선언하도록 하고 있다. 만약 x:TypeArguments값이 제너릭 타입 PageFunction의 인자와 일치하지 않으면 컴파일 에러가 발생한다

PageFunciton을 호출하려면 호출 페이지는 PageFunction을 인스턴스화시켜서 그것으로 네비게이트해야 한다.

// HomePage.cs (codebehind)

public partial class HomePage : Page

{

  void orderHyperlink_Click(object sender, RoutedEventArgs e)

  {

  OrderABoxPageFunction pageFunction = new OrderABoxPageFunction();

  pageFunction.Return += new ReturnEventHandler<Order>(

     OrderABoxPageFunction_Returned);

  this.NavigationService.Navigate(pageFunction);

  }

  ...

}

그런 다음 PageFunction에서는 호출 페이지로 결과를 리턴하기 전에 페이지를 완수하도록 해야 한다.

// OrderABoxPageFunction.cs (codebehind)

public partial class OrderABoxPageFunction:

  PageFunction<Order>

{

  void orderHyperlink_Click(object sender, RoutedEventArgs e)

  {

  // Return order

  this.OnReturn(new ReturnEventArgs<Order>(this.order));

  }

  void cancelHyperlink_Click(object sender, RoutedEventArgs e)

  {

  // Cancel order

  this.OnReturn(null);

  }

  ...

}

PageFunction에서 리턴하려면 PageFunction.OnReturn를 호출하면 된다. 이때 제너릭 타입의 인자ReturnEventArgs 인스턴스를 넘긴다. 만약 태스크가 수락된다면, PageFunction이 대상으로 작업했던 타입(Order)의 인스턴스를 포함하고 있을 것이다. 그렇지 않으면 null을 가지고 있을 것이다. PageFunction이 리턴되는 때를 확인하고 ReturnEventArgs와 그것의 데이터를 얻으려면 호출 페이지에서는 다음처럼 PageFunction.Returned 이벤트를 이용한다. 반환된 데이터는 Returned 핸들러의 ReturnEventArgs의 속성 Result에서 구할 수 있다.

// HomePage.cs (code-behind)

public partial class HomePage : Page

{

  // Launch the page function

  void orderHyperlink_Click(object sender, RoutedEventArgs e)

  {

  OrderABoxPageFunction pageFunction = new OrderABoxPageFunction();

  pageFunction.Return += new ReturnEventHandler<Order>(

       OrderABoxPageFunction_Returned);

  this.NavigationService.Navigate(pageFunction);

  }

  // Handle page function return

  void OrderABoxPageFunction_Returned(

  object sender, ReturnEventArgs<Order> e)

  {

  if (e != null) this.orders.Add(e.Result);

  }

  ...

}

태스크가 완료되면 PageFuntion이 네비게이션 히스토리에서 제거되기를 원할 수도 있다. 그런 경우는단순히 다음 설정만 해주면 된다.

<!--OrderABoxPageFunction.xaml (markup) -->

     <PageFunction RemoveFromJournal="True" ...="" >

       ...

       <!--Content-->

       ...

       <PageFunction>

페이지 펑크션을 네비게이션 히스토리에서 제거함으로써 사용자가 뒤로 네비게이트해서 다시 페이지 펑크션으로 들어가는 것을 막을 수 있다. 그렇지 않다면 사용자는 이미 완료된 태스트의 데이터를 수정함으로써 데이터의 정합성에 문제를 일으킬 수 있는 가능성이 되는 것이다.

주의할 것은 태스크는 하나 이상의 페이지로 이루어질 수 있다. 이것은 위저드 스타일의 사용자 경험에는 흔한 일이다. 이런 경우에도 PageFunction은 적합하다. PageFunction은 하나의 페이지 펑크션을 대상으로 하는 동일한 기술을 여러 페이지에서도 적용할 수 있기 때문이다.

'IT 살이 > 04. 기술 - 프로그래밍' 카테고리의 다른 글

13 Where Are We?  (0) 2009.04.23
11 WPF 리소스  (0) 2009.04.23
10 Frame  (0) 2009.04.23