출처: http://www.microsoft.com/korea/msdn/lib ··· wpf.aspx

Windows Presentation Foundation 설명

기본적으로 기술은 주로 전문가들이 중요하게 생각하는 부분으로 대부분의 소프트웨어 전문가들은 응용 프로그램과 사용자 간의 상호 작용 방식보다는 응용 프로그램의 작동 방식에 훨씬 더 많은 관심을 가집니다. 그러나 응용 프로그램을 구입하는 실제 사용자에게는 사용자 인터페이스가 매우 중요합니다. 응용 프로그램의 인터페이스는 해당 소프트웨어에 대한 전체적인 사용자 환경에서 중요한 부분을 차지하며, 사용자에게 이러한 환경은 응용 프로그램 '그 자체'를 의미합니다. 더 나은 인터페이스를 통해 향상된 사용자 환경을 제공하면 생산성을 높이고 우수 고객을 더 많이 확보할 수 있으며 웹 사이트에서의 매출을 늘리는 등 다양한 효과를 얻을 수 있습니다.

이전에는 문자 기반 인터페이스만으로 충분했지만 오늘날의 사용자들은 그래픽 인터페이스에 익숙해졌으며 사용자 인터페이스에 대한 요구 사항은 계속해서 증가하고 있습니다. 그래픽과 미디어가 더욱 광범위하게 사용되고 있으며 웹의 발전은 소프트웨어와의 편리한 상호 작용을 기대하는 사용자 계층을 형성하게 되었습니다. 사용자들이 응용 프로그램을 사용하는 시간이 늘어날수록 해당 응용 프로그램의 인터페이스는 더욱 중요해집니다. 이렇듯 점점 높아지는 인터페이스 요구 사항에 부응하기 위해서는 사용자 인터페이스를 만드는 기술도 함께 발전해야 합니다.

WPF(Windows Presentation Foundation)의 목표는 Windows에 바로 이러한 고급 기능을 제공하는 것입니다. Microsoft .NET Framework 버전 3.0에 포함된 WPF를 사용하면 문서, 미디어, 2차원 및 3차원 그래픽, 애니메이션, 웹 특성 등을 포함하는 인터페이스를 만들 수 있습니다. WPF는 .NET Framework 3.0의 모든 구성 요소와 마찬가지로 Windows Vista, Windows XP 및 Windows Server 2003에서 사용할 수 있으며 Windows Vista와 함께 출시될 예정입니다. 이 백서에서는 WPF를 소개하고 WPF의 다양한 구성 요소에 대해 설명하며 이 기술을 통해 해결할 수 있는 문제점과 WPF가 제공하는 솔루션에 대해 살펴봅니다.

문제점 예시

병원에서 환자를 진료하고 모니터링하는 데 사용할 새 응용 프로그램을 만든다고 가정해 보겠습니다. 새로 만들 응용 프로그램에는 다음과 같은 사용자 인터페이스가 필요할 수 있습니다.

  • 환자에 대한 이미지와 텍스트 표시
  • 심장 박동수, 혈압 등 환자의 활력 징후를 보여 주는 2차원 그래픽 표시 및 업데이트
  • 환자 정보에 대한 3차원 보기 및 오버레이 제공
  • 초음파 또는 기타 진단 비디오를 표시하고, 가능한 경우 의사나 간호사가 메모를 추가할 수 있는 기능 제공
  • 병원 직원이 환자 및 환자 상태에 대한 기록을 읽고 메모를 추가할 수 있는 기능
  • 병원 직원이 모든 기능을 사용할 수 있도록 Windows 응용 프로그램으로 실행되고 다른 위치에 있는 의사가 인터넷을 통해 제한적인 방식으로 액세스할 수 있도록 엄격한 보안이 유지되는 웹 브라우저 응용 프로그램으로도 실행

이러한 요구 사항은 야심적이기는 하지만 충분히 실현 가능합니다. 필요한 정보를 적시에 적절한 방법으로 제공하는 사용자 인터페이스는 업무상 중요한 가치를 지닙니다. 앞에서 설명한 의료 응용 프로그램의 예에서는 적절한 사용자 인터페이스가 생명을 구할 수도 있습니다. 온라인 상점 또는 기타 고객 지향 응용 프로그램과 같은 일반적인 시나리오의 경우 강력한 사용자 환경을 제공하면 회사의 서비스를 경쟁사의 서비스와 차별화하여 매출 증진은 물론 회사의 브랜드 가치를 높일 수 있습니다. 중요한 점은 많은 수의 최신 응용 프로그램에서 그래픽, 미디어, 문서 및 기타 최신 사용자 환경의 요소를 통합하는 인터페이스를 제공함으로써 다양한 이점을 누릴 수 있다는 것입니다.

2006년 현재의 기술로 Windows에 이러한 유형의 인터페이스를 만들 수도 있지만 이러한 작업은 다음과 같은 주요 장애 요인으로 인해 실현하기 매우 어렵습니다.

  • 그래픽, 이미지 및 비디오로 작업하는 데 서로 다른 여러 기술이 사용됩니다. 이러한 다양한 기술을 활용하기 위해 유능한 개발자를 찾는 것은 이러한 개발자가 만드는 응용 프로그램을 유지 관리하는 것만큼 어렵고 비용도 많이 듭니다.
  • 이러한 모든 기능을 사용자에게 효과적으로 제공하는 인터페이스를 디자인하는 일은 도전적인 과제입니다. 소프트웨어 개발자의 기술만으로는 이러한 인터페이스를 디자인할 수 없기 때문에 전문 디자이너가 필요하지만 여기에서 설명한 모든 기능을 갖춘 인터페이스를 개발하기 위해 디자이너와 개발자가 공동으로 작업하는 데는 많은 제약이 따릅니다.
  • 모든 기능을 갖춘 인터페이스를 독립 실행형 Windows 응용 프로그램 버전과 브라우저에 호스팅되는 버전의 두 가지 형식으로 제공하려면 서로 다른 두 가지 분야의 기술을 사용하여 각 버전을 개별적으로 구현해야 합니다. Windows 데스크톱 응용 프로그램은 Windows Forms 및 기타 기본적인 Windows 기술을 사용하여 구현하고 브라우저에 호스팅되는 응용 프로그램은 HTML 및 JavaScript를 사용하여 구현할 수 있습니다. 이 경우 서로 다른 두 분야의 기술을 갖춘 두 개의 개발자 그룹이 필요합니다.

강력한 기능을 제공하는 최신 사용자 인터페이스를 만드는 작업을 복잡하게 생각할 필요는 전혀 없습니다. 공통적인 기반을 사용하면 이러한 모든 문제를 해결하고 개발자에게 단일화된 접근 방식을 제공하는 동시에 디자이너도 작업에서 중요한 역할을 담당하도록 할 수 있습니다. 이것이 바로 WPF의 목표이며, 자세한 내용은 다음 섹션에서 설명합니다.

문제점 해결: Windows Presentation Foundation의 기능

WPF가 제공하는 가장 중요한 세 가지 특징은 최신 사용자 인터페이스를 제공하기 위한 통합 플랫폼, 개발자와 디자이너가 공동으로 작업할 수 있는 환경, 그리고 Windows 사용자 인터페이스와 웹 브라우저 사용자 인터페이스를 개발하기 위한 공통의 기술입니다. 이 섹션에서는 이러한 세 가지 특징에 대해 설명합니다.

최신 사용자 인터페이스를 제공하기 위한 통합 플랫폼

WPF를 사용하지 않는 환경에서 위 설명과 같은 Windows 사용자 인터페이스를 만들기 위해서는 여러 가지 기술을 함께 사용해야 합니다. 다음 표에서는 필요한 기술을 간략하게 보여 줍니다.

Windows Forms PDF Windows Forms/
GDI+
Windows Media Player Direct3D WPF
그래픽 인터페이스(예: 폼 및 컨트롤) X X
화면에 표시되는 문서 X X
고정된 형식의 문서 X X
이미지 X X
비디오 및 오디오 X X
2차원 그래픽 X X
3차원 그래픽 X X

개발자가 폼, 컨트롤 및 기타 Windows 그래픽 사용자 인터페이스의 일반적인 요소를 만들려면 대개 .NET Framework의 일부인 Windows Forms를 사용해야 합니다. 인터페이스에서 문서를 표시해야 할 경우 Windows Forms에서 부분적으로 지원되는 화면 표시 문서를 사용할 수 있지만 고정된 형식의 문서를 사용해야 할 경우에는 Adobe의 PDF 형식이 적합합니다. 이미지와 2차원 그래픽을 표시하려는 경우 개발자는 Windows Forms를 통해 액세스할 수 있는 고유한 프로그래밍 모델인 GDI+를 사용할 수 있습니다. 또한 비디오와 오디오 기능은 Windows Media Player를 통해 제공하고 3차원 그래픽 기능은 Windows 표준인 Direct3D를 통해 제공할 수 있습니다.

이렇게 복잡한 작업은 단지 이론적인 설명을 위한 것일 뿐이며 이를 실제로 실행하는 것은 적절하지 않다는 데 누구나 동의할 것입니다. 그러나 통합된 단일 솔루션인 WPF에서는 이 모든 것이 가능합니다. WPF가 설치된 컴퓨터에서 응용 프로그램을 만드는 개발자는 WPF 하나만으로 위에서 언급한 모든 문제를 해결할 수 있습니다. 즉, 이제는 여러 가지 독립적인 기술을 사용하는 대신 하나의 일관된 기반을 사용하여 사용자 인터페이스를 만들 수 있습니다.

물론 WPF가 이 표에 나와 있는 모든 기술을 대체하지는 않습니다. Windows Forms 응용 프로그램은 여전히 유용하게 활용될 것이며, WPF 환경에서도 일부 새 응용 프로그램에는 Windows Forms를 사용해야 할 수 있습니다. WPF를 Windows Forms와 상호 운용할 수 있다는 점은 주목할 만한 가치가 있습니다. 이에 대한 자세한 내용은 이 문서의 뒷부분에서 설명합니다. Windows Media Player도 여전히 독자적인 가치를 제공할 것이며 PDF 문서도 계속해서 사용될 것입니다. Direct3D 또한 게임이나 몇 가지 다른 유형의 응용 프로그램에서는 중요한 기술입니다. 실제로 WPF에서도 Direct3D를 통해 모든 렌더링 작업을 수행합니다.

그러나 WPF라는 단일 기술을 통해 광범위한 기능을 제공하면 최신 사용자 인터페이스를 훨씬 쉽게 구현할 수 있다는 장점이 있습니다. 다음 화면에서는 이러한 통합된 접근 방식의 이점을 쉽게 이해할 수 있도록 앞에서 설명한 WPF 기반 버전의 의료 응용 프로그램을 보여 줍니다.

그림 1. WPF 인터페이스에서는 이미지, 텍스트, 2D 그래픽, 3D 그래픽 등을 결합할 수 있습니다.

이 화면에서는 텍스트와 이미지를 비롯하여 2차원 그래픽 및 3차원 그래픽을 함께 볼 수 있습니다. 이 모든 인터페이스는 개발자가 GDI+ 또는 Direct3D와 같은 특수 그래픽 기술을 사용하는 코드를 작성할 필요 없이 WPF를 사용하여 생성되었습니다. WPF를 사용하면 다음 그림에서 볼 수 있는 초음파 진단 결과처럼 비디오를 표시하고 메모를 입력하는 기능을 구현할 수도 있습니다.

그림 2. WPF 인터페이스에는 비디오뿐만 아니라 사용자가 입력할 수 있는 텍스트 메모를 모두 포함할 수 있습니다.

WPF를 사용하면 읽기 편리한 방식으로 문서를 표시할 수 있습니다. 예를 들어 병원 응용 프로그램의 경우 의사가 환자의 처방전에 대한 기록을 조회하거나 관련 항목에 대한 최근의 의학 연구 자료에 액세스할 수 있습니다. 아래의 화면에서 볼 수 있는 것처럼 의사는 메모를 추가할 수 있습니다.

그림 3. WPF 인터페이스에서는 메모를 포함하여 여러 개의 열이 있는 문서를 표시할 수 있습니다.

이 화면에서 문서는 가독성이 뛰어난 열 형식으로 표시되고 사용자는 스크롤 방식이 아니라 문서를 한 페이지씩 이동할 수 있습니다. 화면을 보기 쉽게 표시하는 것도 WPF의 중요한 목표 중 하나입니다. 그러나 화면에 표시되는 문서보다 고정된 형식의 문서를 사용하는 것이 적절한 경우도 있습니다. 고정된 형식의 문서는 화면에서 볼 때나 인쇄했을 때 모양이 동일하기 때문에 항상 일관된 모양을 제공합니다. 이러한 형식의 문서를 정의하기 위해 Microsoft는 XPS(XML Paper Specification)를 만들었습니다. WPF는 개발자가 XPS 문서를 만들고 작업하는 데 사용할 수 있는 API(응용 프로그래밍 인터페이스) 그룹도 제공합니다.

그러나 최신 사용자 인터페이스를 만드는 것은 독립적인 여러 기술을 단순히 통합하는 것이 아니라 최신 그래픽 카드의 장점을 활용할 수 있다는 의미를 가지고 있습니다. 즉, WPF는 시스템의 GPU(Graphics Processing Unit)에 가능한 한 많은 작업 로드를 분산시킴으로써 GPU를 최대한 활용합니다. 또한 최신 인터페이스는 비트맵 그래픽의 한계에 제약을 받지 않아야 하므로 WPF는 화면의 크기와 해상도에 맞게 이미지 크기가 자동으로 조정되도록 벡터 그래픽 기술을 사용합니다. 따라서 개발자는 작은 모니터와 대형 TV 화면에 표시할 그래픽을 개별적으로 만들지 않고 WPF를 통해 이러한 크기 조정 작업을 자동으로 처리할 수 있습니다.

WPF는 사용자 인터페이스를 만드는 데 필요한 모든 기술을 하나의 기반에 집약함으로써 이러한 인터페이스를 만드는 개발자의 업무 부담을 크게 낮추어 줍니다. WPF를 사용하는 경우 개발자는 하나의 작업 환경만 파악하면 되기 때문에 응용 프로그램 개발 및 유지 관리에 소요되는 비용이 훨씬 저렴합니다. 또한 WPF를 사용하면 그래픽, 비디오 등의 다양한 요소가 포함된 인터페이스를 간단하게 구현할 수 있으므로 사용자가 Windows 응용 프로그램과 상호 작용하는 방식을 개선하고 업무 효율성을 높일 수 있습니다.

개발자와 디자이너가 공동으로 작업할 수 있는 환경

모든 기능을 갖춘 사용자 인터페이스를 만들기 위한 통합된 기술 기반을 제공하는 것은 매우 바람직합니다. 그러나 개발자가 외부의 도움 없이 이러한 강력한 기능을 제대로 활용하여 이해하기 쉽고 사용이 편리한 인터페이스를 만들 수 있을 것이라고 기대하는 것은 무리입니다. 특히 앞에서 설명한 병원 사례와 같이 포괄적이고 유용한 사용자 인터페이스를 만들기 위해서는 대부분의 소프트웨어 전문가들이 갖추지 못한 인터페이스 디자인 기술이 필요합니다. 소프트웨어 전문가들이 많은 수의 응용 프로그램을 단독으로 개발하고 있지만 최상의 사용자 인터페이스를 구현하기 위해서는 전문 인터페이스 디자이너의 도움이 필요합니다.

그러나 개발자와 디자이너는 업무 진행 방식이 서로 다르기 때문에 두 분야의 전문가가 공동으로 작업하는 데는 여러 가지 문제가 있습니다. 일반적으로 디자이너는 그래픽 도구를 사용하여 응용 프로그램에 표시할 화면 레이아웃의 정적 이미지를 만듭니다. 그런 다음 이러한 이미지를 개발자에게 전달하고, 개발자는 해당 이미지를 구현하는 코드를 작성합니다. 그러나 디자이너는 만들기 쉽더라도 개발자는 구현하기 어렵거나 전혀 구현할 수 없는 이미지도 있습니다. 예를 들어 개발자는 기술적인 한계, 촉박한 일정, 기술 부족, 사소한 오해 또는 단순한 의견 차이로 인해 디자이너의 의도를 완벽하게 구현하지 못할 수 있습니다. 따라서 최상의 인터페이스를 만들기 위해서는 독립적인 두 분야의 전문가가 인터페이스의 품질을 떨어뜨리지 않으면서 공동으로 작업할 수 있는 환경이 필요합니다.

WPF는 이러한 공동 작업이 가능하도록 XAML(eXtensible Application Markup Language)을 사용합니다. XAML은 사용자 인터페이스의 모양을 정확하게 정의하기 위해 Button, TextBox, Label 등 여러 XML 요소의 집합을 정의합니다. 일반적으로 XAML 요소는 다양한 옵션을 설정할 수 있도록 특성도 포함합니다. 예를 들어 다음의 간단한 XAML 코드는 "아니요"라는 단어가 표시되는 빨간색 단추를 만듭니다.

<Button Background="Red">
 아니요
</Button>

각 XAML 요소는 WPF 클래스에 해당하고 요소의 각 특성은 클래스의 해당 속성이나 이벤트를 갖습니다. 예를 들어 다음과 같은 C# 코드를 사용하여 동일한 빨간색 단추를 만들 수 있습니다.

Button btn = new Button();
btn.Background = Brushes.Red;
btn.Content = "아니요";

XAML로 표현할 수 있는 모든 것을 코드를 사용하여 동일하게 작성할 수 있다면 XAML을 사용할 필요가 없다고 생각할 수도 있습니다. 그러나 XML 기반의 설명을 생성하고 사용하는 작성 도구를 사용하면 코드를 사용하여 동일한 작업을 할 때보다 훨씬 쉽게 작업할 수 있습니다. XAML은 사용이 편리한 도구 방식으로 사용자 인터페이스를 설명하기 때문에 개발자와 디자이너가 더 효율적으로 함께 작업할 수 있습니다. 다음 그림은 이러한 작업 과정을 보여 줍니다.

그림 4. 디자이너와 개발자의 공동 작업을 돕는 XAML

디자이너는 Microsoft Expression Interactive Designer와 같은 도구를 사용하여 사용자 인터페이스의 모양과 상호 작용 방식을 지정할 수 있습니다. 이 도구는 WPF 인터페이스의 모양과 느낌을 정의하는 용도로 사용되며 해당 인터페이스에 대한 설명을 XAML 표현으로 생성합니다. 예제로 사용된 간단한 단추만 포함하더라도 이 설명은 실제로 위에 나온 코드 조각보다 훨씬 복잡합니다. 개발자는 이 XAML 설명을 Microsoft Visual Studio와 같은 도구로 가져옵니다. 이렇게 하면 디자이너가 만든 정적 이미지를 토대로 인터페이스를 처음부터 다시 만들 필요 없이 인터페이스 정의 자체를 그대로 가져올 수 있습니다. 그런 다음 개발자는 이벤트 처리기와 같이 인터페이스에 필요한 코드 및 응용 프로그램에 필요한 기타 기능에 해당하는 코드를 작성합니다. 또한 응용 프로그램 인터페이스에 전체적으로 적용할 수 있는 스타일을 만들 수도 있으며, 이러한 스타일은 나중에 필요에 따라 사용자 지정할 수 있습니다.

디자이너와 개발자가 이러한 방식으로 함께 작업하면 디자이너가 만든 이미지를 토대로 개발자가 인터페이스를 구현할 경우 발생할 수 있는 변환 오류를 줄일 수 있을 뿐만 아니라 이러한 두 분야의 전문가가 반복 작업을 신속하게 수행하고 효과적으로 의견을 교환하면서 동시에 작업을 진행할 수 있습니다. 또한 두 환경 모두에서 동일한 빌드 시스템을 사용하므로 두 개발 환경 간에 WPF 응용 프로그램을 주고 받을 수도 있습니다. 3차원 인터페이스 요소를 만들기 위한 Electric Rain의 ZAM 3D와 같이 XAML로 정의된 인터페이스를 디자인하는 데 사용할 수 있는 특수한 도구도 있습니다.

더 나은 인터페이스를 사용하면 생산성을 높일 수 있을 뿐만 아니라 여러 가지 측면에서 업무상 매우 유용합니다. 그러나 효과적인 인터페이스를 만드는 데는 특히 WPF가 제공하는 다양한 환경의 경우 디자이너의 역할이 가장 중요합니다. XAML 및 XAML을 지원하는 도구의 기본적인 목표는 디자이너의 작업을 돕는 것입니다.

Windows 사용자 인터페이스와 웹 브라우저 사용자 인터페이스를 개발하기 위한 공통의 기술

Windows 응용 프로그램에 사용할 효과적인 사용자 인터페이스를 만드는 것도 중요하지만 웹 기반 응용 프로그램에 사용할 효과적인 인터페이스를 만드는 것도 그만큼 중요합니다. 기본적으로 이러한 인터페이스는 웹 브라우저에서 제공합니다. 인터페이스를 만드는 가장 간단한 방법은 브라우저에 전달되는 모든 HTML을 브라우저가 수동적으로 표시하도록 하는 것입니다. 응답 성능이 더 뛰어난 브라우저 인터페이스에서는 대개 AJAX(Asynchronous JavaScript And XML)를 사용하여 JavaScript로 실행되는 논리를 제공합니다. Adobe Flash Player 또는 몇 가지 다른 기술을 사용하여 애니메이션, 비디오 등을 인터페이스에 사용할 수도 있습니다. 이와 같이 기능이 다양한 인터페이스 유형을 제공하는 웹 소프트웨어를 '다기능 인터넷 응용 프로그램'이라고도 합니다. 이 웹 소프트웨어를 사용하면 사용자 환경을 크게 향상시킬 수 있을 뿐만 아니라 더 많은 사용자의 참여를 유도하는 웹 응용 프로그램을 만들어 상당한 비즈니스 가치를 얻을 수 있습니다.

일반적으로 이러한 유형의 인터페이스를 구현하기 위해서는 기본적인 Windows 인터페이스에 사용되는 것과는 완전히 다른 기술을 사용해야 합니다. 결과적으로 개발자는 서로 다른 두 가지 작업, 즉 Windows 인터페이스를 개발하는 작업 또는 웹 인터페이스 개발하는 작업 중 하나에 초점을 두고 작업해야 합니다. 그러나 Windows에서 액세스할 다기능 인터넷 응용 프로그램을 만드는 데 이러한 양분된 방식으로 작업할 필요는 없으며 기본적인 Windows 인터페이스와 웹 브라우저 인터페이스 모두에 동일한 기술을 사용하지 못할 이유도 없습니다.

WPF를 사용하면 동일한 기술을 사용하여 Windows 인터페이스와 웹 브라우저 인터페이스 모두를 만드는 것이 가능합니다. 개발자는 WPF를 사용하여 Internet Explorer에서 실행되는 XBAP(XAML Browser Application)를 만들 수 있습니다. 실제로 동일한 코드를 사용하여 독립 실행형 WPF 응용 프로그램과 XBAP를 만들 수 있습니다. 예를 들어 아래의 화면에서는 독립 실행형 Windows 응용 프로그램으로 실행되는 재무 서비스 응용 프로그램을 보여 줍니다. 앞에서 설명한 병원 응용 프로그램과 마찬가지로 이 응용 프로그램도 텍스트, 이미지 및 다양한 종류의 그래픽을 함께 사용합니다. 이 화면에서는 시계 등의 가젯 및 응용 프로그램 창 주위에 반투명 테두리를 사용하는 Aero 테마가 적용된 Windows Vista 바탕 화면도 볼 수 있습니다.

그림 5. 재무 서비스 응용 프로그램을 독립 실행형 WPF 응용 프로그램으로 실행할 수 있습니다.

다음 그림에서는 이 인터페이스를 Internet Explorer에서 XBAP로 실행할 때의 모양을 보여 줍니다.

그림 6. 동일한 응용 프로그램을 XBAP로도 실행할 수 있습니다.

이 경우 인터페이스가 자체 창에서 실행되는 대신 브라우저에서 실행된다는 점만 다를 뿐 모든 기능은 동일합니다. 두 경우 모두에 동일한 코드를 사용하면 두 가지 유형의 인터페이스를 개별적으로 만드는 데 소요되는 것보다 작업량을 줄일 수 있습니다. 동일한 코드를 사용한다는 것은 동일한 개발자를 투입할 수 있음을 의미합니다. WPF를 사용하면 개발자를 Windows 인터페이스 개발자 또는 웹 인터페이스 개발자라는 분리된 두 개의 그룹으로 구분할 필요 없이 하나의 개발 리소스를 두 작업 모두에 활용할 수 있습니다.

동일한 기술을 사용하여 Windows 인터페이스와 웹 인터페이스를 만들면 응용 프로그램 작성자가 응용 프로그램의 인터페이스 유형을 미리 결정하지 않아도 된다는 또 하나의 장점이 있습니다. 즉, 대상 클라이언트가 XBAP를 실행하는 데 필요한 요구 사항을 충족하기만 하면 응용 프로그램에서는 거의 동일한 코드를 사용하여 Windows 인터페이스나 웹 인터페이스 또는 두 가지 인터페이스 모두를 제공할 수 있습니다.

XBAP는 필요할 때 웹 서버에서 다운로드되기 때문에 독립 실행형 Windows 응용 프로그램에 비해 더욱 엄격한 보안 요구 사항이 적용됩니다. 이러한 이유로 XBAP는 .NET Framework의 코드 액세스 보안에서 제공하는 보안 샌드박스(Security Sandbox)에서 실행됩니다. 또한 XBAP는 WPF가 설치되어 있는 Windows 시스템에서 Internet Explorer 버전 6 및 7에서만 실행됩니다. 이러한 요구 사항이 충족되면 인터넷 응용 프로그램이 독립 실행형 Windows 응용 프로그램과 동일한 기반을 활용하는 것이 가능합니다.

Windows Presentation Foundation 사용

WPF로 해결할 수 있는 문제점만 알고 있어도 도움이 되지만 WPF가 이러한 문제점을 해결하는 방법을 이해한다면 더 큰 도움이 됩니다. 이 섹션에서는 WPF 기술 자체를 자세하게 살펴본 후 Windows 데스크톱 응용 프로그램, XBAP 및 XPS 문서에 WPF 기술이 적용되는 다양한 방식에 대해 알아봅니다.

Windows Presentation Foundation의 기술

WPF는 사용자 인터페이스를 만들기 위한 통합된 기반을 제공하지만 WPF에 포함된 기술을 문서, 이미지, 그래픽, 애니메이션 등과 같은 개별 단위로 나누어 살펴볼 수 있습니다. 이러한 모든 개별 단위는 다음에 설명할 WPF의 기본 응용 프로그램 모델에 의존합니다.

응용 프로그램 모델

.NET Framework의 다른 구성 요소와 마찬가지로 WPF의 기능은 System.Windows 네임스페이스에 포함된 네임스페이스 그룹으로 나뉩니다. 모든 WPF 응용 프로그램의 기본 구조는 어느 기능을 사용하는지에 관계없이 거의 동일합니다. 일반적으로 응용 프로그램은 독립 실행형 Windows 응용 프로그램이나 XBAP에 관계없이 XAML 페이지 집합과 이들 페이지에 연결된 코드로 구성됩니다.

기본적으로 모든 응용 프로그램은 WPF의 표준 Application 클래스에서 상속됩니다. 이 클래스는 모든 응용 프로그램에서 유용하게 사용할 수 있는 공통 서비스를 제공하며, 여기에는 전체 응용 프로그램에 필요한 상태를 유지하는 서비스 및 응용 프로그램을 시작하는 Run, 응용 프로그램을 종료하는 Shutdown 등의 표준 메서드를 제공하는 서비스가 포함됩니다.

Application 개체는 Application 요소를 통해 XAML을 사용하여 만들거나 Application 클래스를 통해 코드를 사용하여 만들 수 있습니다. 이러한 특징은 사실상 WPF의 모든 요소에 적용되지만 이 문서에서는 간단히 설명하기 위해 XAML을 사용하는 방식만을 소개할 것입니다. 다음은 간단한 XAML을 보여 줍니다.

<Application xmlns=   
    "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     StartupUri="Page1.xaml"
     x:Class="Example.SimpleApp">
. . . 
</Application>

이 정의에서는 먼저 WPF 네임스페이스를 이 요소의 기본값으로 지정한 다음 XAML 네임스페이스의 접두사를 정의합니다. XAML은 WPF에만 사용되는 것이 아니므로 이 두 네임스페이스는 서로 다릅니다. 다음으로 StartupUri 특성을 사용하여 응용 프로그램을 시작했을 때 로드하고 표시할 XAML 페이지의 이름을 나타냅니다. 마지막 특성인 Class는 이 Application과 관련된 코드가 들어 있는 클래스를 식별하는 데 사용됩니다. 앞에서 살펴본 것처럼 일반적으로 WPF 응용 프로그램에는 C# 또는 Visual Basic으로 작성된 코드와 XAML이 모두 들어 있으므로 이 클래스의 코드는 '코드 숨김' 파일에 저장됩니다. 여는 Application 태그 다음에는 이 응용 프로그램을 정의하는 데 필요한 나머지 XAML이 위치하고(여기에서는 생략됨), 마지막으로 Application 요소의 닫는 태그가 위치합니다.

모든 WPF 응용 프로그램은 동일한 루트 클래스에서 파생되지만 개발자는 다양한 옵션을 선택할 수 있습니다. 그 중 가장 중요한 옵션은 응용 프로그램에 일반적인 대화 상자 형식의 인터페이스를 사용할지 아니면 탐색 형식의 인터페이스를 사용할지 결정하는 것입니다. 대화 상자 형식의 인터페이스는 Windows 사용자라면 누구나 익숙한 단추 및 기타 요소를 제공합니다. 반면 탐색 형식의 인터페이스는 브라우저와 동작 방식이 거의 유사합니다. 예를 들어 탐색 형식의 인터페이스를 사용하면 대화 상자가 새 창에서 열리는 대신 새 페이지가 로드됩니다. 이와 같은 인터페이스는 페이지 그룹으로 구현되며, 각 페이지는 XAML에 정의된 사용자 인터페이스와 프로그래밍 언어로 표현된 논리로 구성됩니다. HTML로 정의된 브라우저 페이지와 마찬가지로 XAML은 페이지를 서로 연결하는 데 사용할 수 있는 Hyperlink 요소를 제공합니다. 사용자는 웹 기반 응용 프로그램의 페이지를 탐색할 때와 같은 방법으로 기록 목록을 통해 앞으로 또는 뒤로 이동하면서 여러 페이지를 탐색할 수 있습니다. 그러나 이것은 Windows 응용 프로그램이므로 혼동하지 말아야 합니다. 일반적으로 XBAP에서 이러한 유형의 인터페이스를 사용하지만, 필요에 따라 독립 실행형 Windows 응용 프로그램에서도 탐색 형식의 인터페이스를 통해 사용자와 상호 작용할 수 있습니다. 어떤 방식을 사용할지는 응용 프로그램을 만드는 개발자의 선택에 달려 있습니다.

응용 프로그램에서 어떤 인터페이스 스타일을 사용하든지 여부에 관계없이 응용 프로그램은 일반적으로 하나 이상의 창을 표시합니다. WPF는 창을 표시하기 위한 몇 가지 옵션을 제공합니다. 기본 Window 클래스에서는 창을 표시하고 숨기고 닫는 등의 기본적인 창 기능을 제공합니다. 일반적으로 탐색 형식의 인터페이스를 사용하지 않는 WPF 응용 프로그램에서 이 클래스를 사용합니다. NavigationWindow 클래스는 탐색 형식의 인터페이스를 사용하는 응용 프로그램에서 사용하며 기본 Window 클래스에 탐색 기능이 추가됩니다. 추가적인 탐색 기능으로는 응용 프로그램에서 새 페이지로 이동하는 데 사용할 수 있는 Navigate 메서드, 사용자의 탐색 기록을 저장하는 추적 정보 및 다양한 탐색 관련 이벤트가 있습니다.

레이아웃 및 컨트롤

WPF 응용 프로그램에서는 인터페이스의 다양한 요소를 구성하기 위해 '패널'을 사용하여 레이아웃을 지정합니다. 각 패널에는 단추, 텍스트 상자 등의 '컨트롤' 및 다른 패널이 자식 요소로 포함될 수 있습니다. 패널 종류마다 서로 다른 레이아웃 옵션을 제공합니다. 예를 들어, 이름에서 알 수 있듯이 DockPanel을 사용하면 자식 요소를 패널 가장자리에 도킹하여 배치할 수 있고, Grid를 사용하면 자식 요소를 눈금 위에 정확하게 배치할 수 있습니다. 이때 개발자는 눈금의 행 및 열 개수를 정의한 다음 자식 요소를 배치할 정확한 위치를 지정해야 합니다. Canvas를 사용하면 패널 경계 내의 아무 곳에나 자식 요소를 자유롭게 배치할 수 있습니다.

WPF는 다른 사용자 인터페이스 기술과 마찬가지로 다양한 컨트롤 집합을 제공합니다. 개발자는 사용자 지정 컨트롤을 만들 수도 있습니다. 표준 컨트롤 집합에는 Button, Label, TextBox, ListBox, Menu, Slider 및 기타 일반적인 사용자 인터페이스 디자인 요소가 포함됩니다. 또한 SpellCheck, PasswordBox, 잉크(예: Tablet PC)로 작업하는 데 필요한 컨트롤 등 보다 복잡한 컨트롤도 사용할 수 있습니다.

WPF 응용 프로그램에서는 일반적인 그래픽 인터페이스와 마찬가지로 마우스 이동 및 키 누르기 동작과 같이 사용자가 생성하는 이벤트를 컨트롤을 통해 포착하고 처리할 수 있습니다. 컨트롤 및 기타 사용자 인터페이스 요소는 XAML을 사용하여 완벽하게 지정할 수 있지만 이벤트는 코드에서 처리해야 합니다. 예를 들어 다음 XAML에서는 Canvas에 간단한 Button을 정의합니다.

<Canvas xmlns=
   "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="Example.CodeForCanvas">
  <Button Click="Button_Click">
   여기를 클릭하십시오.
  </Button>
</Canvas>

여는 Canvas 태그는 일반적인 WPF 및 XAML 네임스페이스 정의로 시작됩니다. 다음으로 이 XAML과 관련된 코드를 .NET Framework 네임스페이스 Example에 들어 있는 CodeForCanvas 클래스에서 찾을 수 있음이 지정되고, 그 다음에 "여기를 클릭하십시오."라는 화면 표시 텍스트를 지정하는 Button이 정의됩니다. 여는 Button 태그의 Click 특성은 이 단추의 click 이벤트가 Button_Click이라는 메서드를 사용하여 처리됨을 나타냅니다. 다음은 이 메서드의 코드입니다.

namespace Example {
  public partial class CodeForCanvas : Canvas  {
    void Button_Click(object sender, RoutedEventArgs e)    {
      Button btn = e.Source as Button;
      btn.Background = Brushes.Purple; 
    }
  }
}

네임스페이스 및 클래스의 이름은 위의 Canvas 태그에 지정된 것과 일치합니다. CodeForCanvas 클래스는 WPF에서 제공하는 기본 Canvas 클래스에서 상속되며 partial 클래스로 정의됩니다. Partial 클래스는 .NET Framework 버전 2.0에 새로 추가된 요소로서 개별적으로 정의된 코드를 단일 클래스로 결합하는 데 사용됩니다. 이 경우 XAML로 정의한 Canvas에서 생성되는 partial 클래스와 이 코드의 partial 클래스가 결합됩니다. 그 결과 단추가 포함된 캔버스를 표시하고 해당 단추의 이벤트도 처리할 수 있는 완전한 클래스가 생성됩니다.

이벤트를 처리하는 Button_Click 메서드는 CodeForCanvas 클래스 안에 선언됩니다. 이 메서드는 일반적인 .NET Framework 규칙에 따라 이벤트를 처리하지만 이벤트의 인수는 WPF로 정의된 RoutedEventArgs 클래스를 사용하여 전달됩니다. 이 클래스의 Source 속성은 이벤트를 생성한 Button에 대한 참조를 포함하며 메서드는 이 정보를 사용하여 단추의 색을 보라색으로 변경합니다.

이러한 간단한 예제에서 볼 수 있는 것처럼 WPF 사용자 인터페이스의 요소는 시각적 트리 형식으로 구성됩니다. 이 예제에서는 트리가 Canvas와 유일한 자식 요소인 Button으로 구성되지만 실제 WPF 응용 프로그램에서는 일반적으로 트리가 훨씬 더 복잡해집니다. 화면 표시 인터페이스를 실제로 만들려면 이 시각적 트리를 렌더링해야 합니다. WPF는 가능한 한 하드웨어 렌더링을 사용함으로써 응용 프로그램의 컴퓨터에 설치되어 있는 그래픽 카드를 통해 작업을 처리합니다. 그러나 컴퓨터의 그래픽 하드웨어로 작업을 처리할 수 없는 경우 WPF는 자체 소프트웨어를 사용하여 인터페이스를 렌더링합니다. 이러한 결정은 런타임에 WPF에서 내리기 때문에 개발자는 별도의 작업을 할 필요가 없습니다.

렌더링을 하드웨어 또는 소프트웨어에서 처리하는지 여부에 관계없이 WPF는 항상 유지 모드 그래픽이라는 방식을 사용합니다. 응용 프로그램 작성자가 일반적으로 XAML과 코드를 조합하여 시각적 트리의 모양을 정의하면 WPF 자체에 이 트리의 정보가 유지됩니다. 예를 들어 사용자가 창을 표시할 경우 응용 프로그램에서 창 전체 또는 일부를 다시 그릴 필요 없이 WPF에서 이 작업을 자체적으로 처리합니다. 트리를 구성하는 요소는 화면에 픽셀로 저장되지 않고 개체로 저장되기 때문에 WPF는 이러한 유형의 렌더링을 처리하는 데 충분한 정보를 항상 유지합니다. 창과 창에 포함된 컨트롤의 크기를 조정하는 경우에도 WPF는 자체적으로 모든 렌더링을 다시 수행할 수 있습니다. WPF는 선, 타원 등의 그래픽 형태를 파악하고 비트맵이 아니라 벡터 그래픽을 사용하기 때문에 이와 같은 충분한 정보를 사용하여 새로운 크기로 인터페이스를 다시 만들 수 있습니다.

스타일 및 서식 파일

몇 가지 사용자 인터페이스 요소의 모양을 한 번 정의한 다음 그 모양을 여러 번 다시 적용하면 편리한 경우가 있습니다. 예를 들어 HTML 페이지에서는 CSS(Cascading Style Sheet)를 사용하여 이러한 작업을 수행할 수 있습니다. WPF에서는 '스타일'이 이와 유사한 기능을 합니다. 이미 널리 사용되고 있는 CSS 스타일시트의 경우에서 볼 수 있듯이 스타일을 정의하는 기능을 매우 유용하게 사용할 수 있습니다. 예를 들어 스타일을 사용하면 디자이너와 개발자의 작업 영역을 보다 명확하게 구분할 수 있기 때문에 디자이너가 인터페이스에 일관된 모양을 만들면 개발자는 이러한 세부 사항에 신경쓰지 않아도 됩니다.

WPF 응용 프로그램 작성자는 XAML의 Style 요소를 사용하여 특정 항목의 모양에 대한 특징을 하나 이상 정의한 후 해당 스타일을 반복적으로 적용할 수 있습니다. 예를 들어 ButtonStyle이라는 스타일을 다음과 같이 정의할 수 있습니다.

<Style x:Key="ButtonStyle">
  <Setter Property="Control.Background" Value="Red"/>
  <Setter Property="Control.FontSize" Value="16"/>
</Style>

이 스타일을 사용하여 정의하는 모든 단추에는 빨간색 배경이 사용되고 글꼴 크기가 16으로 지정됩니다. 예를 들면 다음과 같습니다.

  <Button Style="{StaticResource ButtonStyle}">
   여기를 클릭하십시오.
  </Button>

이 예제에 나와 있는 "StaticResource"의 형태에서 알 수 있듯이 일반적으로 WPF 스타일은 리소스로 정의됩니다. 리소스는 응용 프로그램 코드와는 별도로 정의되는 데이터입니다.

스타일은 이 예제에서 설명한 것보다 훨씬 다양한 기능을 제공합니다. 예를 들어 다른 스타일에서 스타일을 파생시킬 수 있습니다. 이 경우 원래의 설정을 상속하거나 필요에 따라 재정의할 수 있습니다. 스타일을 사용하면 대화형 동작의 일반적인 측면을 지정하는 '트리거'를 정의할 수도 있습니다. 예를 들어 마우스로 단추를 가리키면 단추 배경이 노란색으로 바뀌도록 스타일을 지정할 수 있습니다.

WPF는 '서식 파일' 기능도 지원합니다. 서식 파일은 스타일과 유사하며, 다음과 같은 두 가지 유형으로 나뉩니다.

  • 데이터 서식 파일: XAML의 DataTemplate 요소를 사용하여 데이터 표시 방법에 대한 특성 그룹을 지정할 수 있습니다. 데이터 서식 파일에 색, 정렬 방식 등의 특성을 정의한 후 응용 프로그램의 사용자 인터페이스에 자유롭게 사용할 수 있습니다.
  • 컨트롤 서식 파일: XAML의 ControlTemplate 요소를 사용하여 컨트롤의 모양을 정의할 수 있습니다.

응용 프로그램의 인터페이스 모양을 간단하게 정의할 수 있는 방법을 제공하면 응용 프로그램 작성자가 작업하는 데 큰 도움이 될 수 있습니다. WPF에서는 기본적으로 스타일과 서식 파일을 통해 인터페이스 모양을 보다 쉽게 정의할 수 있습니다.

텍스트

대부분의 사용자 인터페이스에는 적어도 어느 정도의 텍스트가 표시되고, 다른 특성은 거의 없이 텍스트만 표시되는 사용자 인터페이스도 있습니다. 그러나 대다수의 사용자들은 화면에서 텍스트를 읽는 것보다 인쇄된 페이지를 읽는 것을 더 선호합니다. 사람들은 책이나 잡지에서 일반적으로 볼 수 있는 고품질의 문자 모양과 글자에 익숙해져 있기 때문에 화면에 표시되는 텍스트를 읽을 때는 왠지 모르게 불편함을 느끼는 것이 사실입니다.

WPF는 인쇄된 페이지를 읽는 것처럼 화면 표시 텍스트도 편하게 읽을 수 있도록 이러한 차이를 줄이는 것을 목표로 합니다. 이러한 목표의 일환으로 WPF에서는 기존 글꼴 라이브러리를 사용할 수 있도록 산업 표준의 OpenType 글꼴은 물론 최근에 정의된 ClearType 기술도 지원합니다. ClearType은 최신 모니터에서 각 픽셀을 구성하는 하위 요소를 개별적으로 다듬는 기법인 하위 픽셀 위치 조정을 통해 텍스트를 보다 매끄럽게 표시하는 기술입니다. WPF는 또한 Glyphs 클래스를 통한 텍스트 렌더링 기능을 부분적으로 지원합니다. 이 클래스는 XPS 문서에서 문자를 나타내는 데 사용되며, 자세한 내용은 이 문서의 뒷부분에서 설명합니다.

WPF는 가독성을 높이기 위해 문자 그룹을 연결된 단일 이미지로 대체하는 합자 방식도 지원합니다. 예를 들어 "ffi"라는 문자 그룹은 일반적으로 인쇄 페이지에서는 이 세 문자가 들어 있는 연결된 단일 합자로 대체됩니다. 이 합자를 화면 표시 텍스트에 사용하면 사용자는 사용된 세부적인 기술은 눈치채지 못한 채 인쇄된 페이지를 보는 것처럼 텍스트를 편하게 읽을 수 있습니다.

문서

텍스트는 단추, 목록 및 사용자 인터페이스의 다른 여러 요소에 표시되므로 텍스트의 가독성을 높이는 것은 매우 바람직합니다. 그러나 텍스트는 문서에서와 같이 더 긴 단락 형식으로 표시되는 경우에 그 기능이 더 중요합니다. 따라서 화면 표시 가독성을 높이기 위해서는 문서가 표시되는 방법도 함께 개선해야 합니다. 이를 위해 WPF에서는 두 가지 유형의 문서, 즉 '고정' 문서와 '동적' 문서를 지원합니다.

고정 문서는 화면에서 렌더링할 때나 인쇄할 때의 모양이 동일합니다. 일부 양식, 법률 문서, 기타 출판물 유형 등 문서 모양을 항상 일관되게 유지해야 하는 경우에는 고정된 형식의 문서를 사용하는 것이 좋습니다. WPF에서 지원하는 고정된 형식의 문서는 XPS로 정의됩니다. XPS에 대한 자세한 내용은 이 문서의 뒷부분에서 설명합니다. 고정 문서의 내용은 XAML의 FixedDocument 요소를 사용하여 지정할 수 있습니다. 이 간단한 요소에는 PageContent 요소의 목록만 포함되고, 각 PageContent 요소에는 고정 문서에 포함된 각 페이지의 이름이 들어 있습니다. WPF에서는 DocumentViewer 컨트롤을 사용하여 고정 문서를 표시합니다. 이 컨트롤은 XPS 문서를 읽기 전용 모드로 표시하고, 사용자는 문서에서 뒤로 또는 앞으로 이동하거나 특정 텍스트를 검색하는 등의 작업을 할 수 있습니다.

고정 문서가 화면과 인쇄 용지 모두에서 사용할 수 있는 문서 유형이라면 동적 문서는 화면 표시 전용 문서입니다. 동적 문서는 문서 내용의 가독성을 최대한 높이기 위해 창 크기와 기타 요인에 따라 텍스트와 그래픽을 자동으로 조정하여 표시합니다. 고정 문서에 대한 설명을 통해 예상할 수 있듯이 동적 문서는 FlowDocument라는 XAML 요소를 사용하여 정의됩니다. 다음은 간단한 예제입니다.

  <FlowDocument 
    ColumnWidth="300" 
    IsColumnWidthFlexible="True" 
    IsHyphenationEnabled="True">
      <Paragraph FontSize="12">
       <Bold>WPF 설명</Bold>
      </Paragraph>
      <Paragraph FontSize="10">
       WPF는 .NET Framework 3.0을 위한 사용자 인터페이스 
       기술입니다. WPF는 문서, 2차원 및 3차원 그래픽, 미디어 등을 
       지원할 뿐만 아니라 최신 사용자 인터페이스를 만들기 위한 
       통합된 기반을 제공합니다. 또한 동일한 방법과 동일한 코드를 
       사용하여 독립 실행형 Windows 응용 프로그램 및 브라우저 
       내에서 실행되는 응용 프로그램을 만들 수 있도록 
       지원합니다.
      </Paragraph>
  </FlowDocument>

이 문서는 너비가 300이상인 열에 표시되도록 지정됩니다. 이때 너비는 각 픽셀이 1/96인치인 '장치 독립적 픽셀' 단위로 측정됩니다. 그러나 문서 작성자는 바로 다음 줄에 IsColumnWidthFlexible 속성을 true로 설정하여 이 너비를 변경 가능하도록 설정했습니다. 이 설정은 이 문서를 표시하는 데 사용되는 열의 개수와 너비를 WPF에서 변경할 수 있도록 허용합니다. 예를 들어 이 문서가 표시되는 창의 너비를 사용자가 변경하면 WPF에서는 문서의 텍스트를 표시하는 데 사용되는 열의 개수와 너비를 적절하게 늘리거나 줄일 수 있습니다.

다음으로 이 문서에서는 하이픈을 사용하도록 IsHyphenationEnabled 속성이 true로 설정되었습니다. 바로 아래에는 이 문서에 포함된 두 개의 단락이 나옵니다. 각 단락의 텍스트는 글꼴 크기가 서로 다르게 설정된 두 개의 Paragraph 요소 안에 각각 들어 있고 첫 번째 단락의 텍스트는 굵게 표시되도록 설정되었습니다.

WPF에서는 가독성을 높이기 위한 몇 가지 FlowDocument 옵션을 추가적으로 정의합니다. 예를 들어 IsOptimalParagraphEnabled 속성을 true로 설정하면 WPF는 단락 전체에서 공백을 가능한 한 균등하게 사용합니다. 이 속성을 사용하면 가독성을 떨어뜨리는 "연속적인" 공백이 나타나는 것을 방지할 수 있습니다. 이 방법은 인쇄된 문서에 일반적으로 사용됩니다. 동적 문서에는 일반 텍스트나 잉크(Tablet PC에 해당)에 노트를 추가하는 것과 같이 메모를 사용할 수도 있습니다. 각 메모는 문서에서 메모가 연결되어 있는 내용을 식별하는 '앵커(anchor)'와 메모 내용 자체가 들어 있는 '카고(cargo)'로 구성됩니다.

WPF에서는 다음과 같은 몇 가지 컨트롤을 사용하여 FlowDocument를 표시할 수 있습니다.

  • FlowDocumentPageViewer: 문서에서 한 번에 한 페이지씩 이동할 수 있습니다. 이 컨트롤은 앞으로/뒤로 단추 및 문서 크기를 조정하는 데 사용할 수 있는 확대/축소 컨트롤을 제공합니다.
  • FlowDocumentScrollViewer: 페이지 오른쪽에 있는 스크롤 막대를 사용하여 문서를 스크롤하는 일반적인 보기 형식으로 FlowDocument를 표시합니다.
  • FlowDocumentReader: FlowDocumentPageViewerFlowDocumentScrollViewer의 기능을 결합한 형식으로 문서를 표시합니다. 이 컨트롤을 사용하면 사용자가 동적 문서의 페이지 단위 보기(두 페이지씩 보기 포함)와 스크롤 보기 사이를 전환할 수 있습니다.

디지털 방식으로 전달되는 정보가 증가함에 따라 화면 표시 가독성도 점차 그 중요성이 높아지고 있습니다. WPF는 동적 문서를 통해 정보를 보다 효과적으로 표시함으로써 더욱 편리한 Windows 사용자 환경을 제공합니다.

이미지

회사 로고, 노을 사진 등 이미지는 많은 사용자 인터페이스의 기본 요소입니다. WPF에서 이미지는 일반적으로 Image 컨트롤을 사용하여 표시됩니다. 예를 들어 JPEG 파일을 표시하려면 다음과 같은 XAML을 사용할 수 있습니다.

<Image 
 Width="200" 
 Source="C:\Documents and Settings\All Users\Documents\
  My Pictures\Ava.jpg" />

이 예제에서는 이미지 너비를 200으로 설정합니다. 이 경우에도 장치 독립적 픽셀 단위가 사용됩니다. Source 특성은 이미지가 들어 있는 파일을 식별합니다.

이미지 파일에는 키워드, 사용자가 지정한 등급 등 이미지에 대한 정보를 나타내는 메타데이터가 들어 있으며 WPF 응용 프로그램에서는 이 정보를 읽고 기록할 수 있습니다. 회전하는 3차원 개체에 그림을 그리는 것처럼 더 재미있는 방법으로 이미지를 사용할 수도 있습니다. 이 문서에 포함된 간단한 예제에서는 가장 일반적인 이미지 사용 방법을 보여 주지만 WPF에서 이미지를 사용하는 방법은 이보다 훨씬 다양합니다.

WPF의 Image 컨트롤은 JPEG, BMP, TIFF, GIF, PNG 등의 다양한 형식뿐만 아니라 Windows Vista에 새롭게 추가된 Microsoft Windows Media Photo(WMPhoto) 형식의 이미지도 표시할 수 있습니다. 이미지 형식에 관계없이 WPF는 WIC(Windows Imaging Component)를 사용하여 이미지를 생성합니다. WIC는 위에서 언급한 모든 이미지 형식에 대한 코더/디코더(일반적으로 '코덱'이라고 함)뿐만 아니라 타사 코덱을 추가할 수 있는 프레임워크도 제공합니다.

비디오 및 오디오

네트워크 및 프로세서 속도가 빨라짐에 따라 비디오는 사용자가 소프트웨어와 상호 작용하는 방식에서 중요한 부분을 차지하게 되었습니다. 또한 사용자들은 컴퓨터에서 음악이나 기타 오디오를 듣는 데 많은 시간을 보내기도 합니다. 이러한 요구에 부응하기 위해 WPF는 비디오 및 오디오 기능을 기본적으로 제공합니다.

비디오 및 오디오 기능은 MediaElement 컨트롤을 통해 제공됩니다. 다음은 이 컨트롤을 사용하는 간단한 XAML 예제입니다.

<MediaElement 
 Source="C:\Documents and Settings\All Users\Documents\
  My Videos\Ruby.wmv" /> 

이 컨트롤은 WMV, MPEG 및 AVI 비디오와 다양한 형식의 오디오를 재생할 수 있습니다.

2차원 그래픽

지난 20년 동안 Windows용 2차원 그래픽 작성자들은 GDI(Graphics Device Interface)와 그 후속 버전인 GDI+를 사용해왔습니다. 그러나 2차원 그래픽은 사용자 인터페이스 기술에 통합되어 있지 않기 때문에 Windows Forms 응용 프로그램에서도 별도의 네임스페이스를 통해 이 기능에 액세스해야 합니다. 3차원 그래픽의 경우에는 완전히 다른 기술인 Direct3D를 사용해야 하기 때문에 작업이 더 번거로웠습니다. 그러나 WPF를 사용하면 대부분의 응용 프로그램에서 이러한 복잡한 작업 과정을 단순화할 수 있습니다. 즉, 2차원 그래픽과 3차원 그래픽 모두를 XAML에서 직접 만들거나 WPF 라이브러리를 사용하여 프로시저 코드에서 만들 수 있습니다. 이러한 작업에 사용되는 요소는 WPF의 다른 모든 요소와 마찬가지로 응용 프로그램의 시각적 트리의 일부입니다.

2D 그래픽의 경우 WPF는 응용 프로그램에서 이미지를 만드는 데 사용할 수 있도록 다음과 같은 '모양' 그룹을 정의합니다

  • Line: 두 지점 사이에 직선을 그립니다.
  • Elllipse: 타원을 그립니다.
  • Rectangle: 사각형을 그립니다.
  • Polygon: 서로 연결된 직선의 그룹으로 정의되는 닫힌 모양을 그립니다.
  • Polyline: 서로 연결된 직선의 그룹으로 정의되는 열린 모양을 그립니다.
  • Path: 임의의 경로로 표시되는 모양을 그립니다. 열린 모양이나 닫힌 모양을 사용할 수 있으며 경로에는 직선이나 곡선을 사용할 수 있습니다. Path를 사용하면 실제로 선, 타원, 사각형, 다각형, 다중선 등을 모두 그릴 수 있기 때문에 다른 모든 모양은 편의를 위해서만 제공됩니다.

이 클래스를 사용하면 간단한 그래픽을 쉽게 만들 수 있습니다. 예를 들어 다음 XAML은 빨간색 타원을 그립니다.

<Ellipse Width="30" Height="10" Fill="Red" />

모양을 채우려면 '브러시'를 사용합니다. 위의 예제에서는 기본값인 단색 브러시를 사용하지만 WPF에서는 몇 가지 다른 옵션도 제공합니다. 예를 들어 다음 예제에서는 가로 방향으로 빨간색에서 노란색으로 바뀌는 색 그라데이션으로 채워진 사각형을 정의합니다.

<Rectangle Width="30" Height="10" 
 Fill="HorizontalGradient Red Yellow" />

이 외에도 이미지, 비트맵 등을 사용하여 그리는 브러시, 수직 그라데이션 및 방사형 그라데이션을 비롯하여 여러 가지 다른 브러시를 사용할 수 있습니다. 이 문서에서 다루지는 않지만 모양에 '펜'을 사용하여 윤곽선의 색, 너비 및 스타일을 지정할 수도 있습니다.

WPF에서는 모든 요소가 공통의 기반에서 구현되므로 서로 다른 요소를 간단하게 결합할 수 있다는 점을 기억해 두십시오. 예를 들어 응용 프로그램에서는 Rectangle 안에 Image를 표시하고, Button 안에 Ellipse를 배치하는 등 다양한 방법으로 요소를 결합할 수 있습니다. 따라서 2D 그래픽을 3D 그래픽 및 다른 인터페이스 요소에 결합하는 것 역시 매우 간단합니다.

WPF는 모양 외에도 2차원 그래픽 작업에 사용할 수 있는 다른 클래스 그룹도 제공합니다. '기하 도형'이라고 하는 이러한 클래스는 모양과 여러모로 비슷합니다. Line, Rectangle, EllipsePath 같은 옵션을 제공하는 모양과 마찬가지로 이 클래스도 LineGeometry, RectangleGeometry, EllipseGeometryPathGeometry 같은 옵션을 제공합니다. 일반적으로 모양은 실제 이미지를 그리는 데 사용되고 기하 도형은 주로 영역을 정의하는 데 사용된다는 것이 이 두 클래스 간의 가장 중요한 차이점입니다. 예를 들어 정사각형 이미지를 원 안에 맞추기 위해 잘라야 할 경우 EllipseGeometry 클래스를 사용하여 원의 경계를 지정할 수 있습니다. 마찬가지로 응용 프로그램에서 마우스 클릭이 감지된 영역과 같이 적중 테스트 영역을 정의해야 하는 경우에는 해당 영역에 기하 도형을 지정하면 됩니다.

이 섹션에서 설명한 모든 내용은 실제로 '시각적 레이어'라는 하위 수준의 인터페이스를 기반으로 구현된다는 점을 알아야 합니다. 이 레이어를 직접 사용하여 그래픽, 이미지 및 텍스트를 만들 수도 있습니다. 간단한 고성능 그래픽을 만들 때와 같이 레이어를 직접 사용하는 방법이 유용할 때도 있지만 대부분의 응용 프로그램에서는 WPF가 제공하는 모양 및 다른 상위 수준의 추상화를 사용합니다.

3차원 그래픽

2차원 그래픽은 Windows 인터페이스의 일반적인 요소이기 때문에 WPF에서는 2차원 그래픽과 관련된 다양한 기술을 제공합니다. 반면, 3차원 그래픽은 뛰어난 데이터 시각화, 3D 차트, 제품 렌더링 등의 다양한 기능을 통해 상당한 가치를 제공할 수 있음에도 불구하고 아직까지는 2차원 그래픽만큼 일반화되지 않았습니다. 이전에는 3D로 작업하기 위해 주로 게임 개발자나 기타 전문 집단에서만 사용하는 고유한 기술을 사용해야 했습니다. 그러나 WPF는 3D 그래픽 기능을 표준 환경에 통합함으로써 이전과는 다른 새로운 작업 환경을 제공합니다.

WPF가 없는 경우 Windows 플랫폼에서는 Direct3D API를 사용하여 3D를 개발해야 합니다. WPF의 다른 요소와 마찬가지로 WPF의 3D 그래픽 기능은 기본적으로 Direct3D에 기반을 두고 있지만 개발자의 실제 작업 환경은 훨씬 단순해졌습니다. 이 문서의 뒷부분에서 설명하는 것처럼 WPF보다는 Direct3D를 사용하는 것이 더 적합한 경우도 있지만, Microsoft의 목표는 Windows 인터페이스에 사용할 대부분의 3D 작업에 WPF를 사용하도록 하는 것입니다.

WPF에서는 응용 프로그램에 Viewport3D 컨트롤을 사용하여 3D 그래픽을 표시합니다. 이 컨트롤은 기본적으로 응용 프로그램에서 나타내는 3차원 공간에 창을 제공합니다. Viewport3D 컨트롤은 WPF 인터페이스의 아무 곳에나 사용할 수 있기 때문에 3D 그래픽을 원하는 위치에 표시하는 것이 가능합니다.

3D 그래픽을 만들 경우 개발자는 하나 이상의 '모델'을 정의한 다음, 이러한 모델에 적용할 조명과 보기 방식을 지정합니다. 이 경우에도 XAML이나 코드 또는 두 방법을 함께 사용하여 모든 옵션을 지정할 수 있습니다. WPF에서는 모델의 모양을 정의할 수 있는 GeometryModel3D 클래스를 사용하여 모델을 정의합니다. 모델을 정의한 후에는 다양한 종류의 '재질'을 사용하여 모델의 모양을 제어할 수 있습니다. 예를 들어 SpecularMaterial 클래스는 표면에 광택 효과를 적용하지만 DiffuseMaterial 클래스는 이 효과를 적용하지 않습니다.

사용한 재질에 관계없이 다양한 방법으로 모델에 조명 효과를 적용할 수 있습니다. DirectionalLight 클래스는 특정 방향의 광원을 제공하고 AmbientLight 클래스는 전체적으로 균일한 조명을 제공합니다. 마지막으로 모델을 보는 방식을 정의하는 '카메라'를 지정합니다. 예를 들어 PerspectiveCamera를 사용하면 모델을 보는 거리와 원근감을 지정할 수 있고, OrthographicCamera를 사용하면 원근감만 제외하고 동일한 옵션을 지정할 수 있습니다. 즉, 이 경우에는 카메라에서 멀리 떨어진 개체도 더 작게 표시되지 않습니다.

XAML 또는 코드에서 직접 복잡한 3D 화면을 만드는 것은 쉽지 않습니다. 3D를 사용하는 대부분의 WPF 응용 프로그램에서 개발자는 그래픽 도구를 사용하여 필요한 정의를 생성하는 경우가 많습니다. 어떤 방법을 사용하든지 표준 사용자 인터페이스에 3D 그래픽을 사용하면 사용자에게 표시되는 화면의 품질을 크게 향상시킬 수 있습니다.

변환 및 효과

WPF에서는 개발자가 모양 및 기타 요소를 정의할 수 있을 뿐만 아니라 회전, 크기 변경 등의 작업을 통해 요소를 변환할 수도 있습니다. XAML에서는 RotateTransformScaleTransform 같은 요소를 사용하여 이러한 작업을 할 수 있습니다. 이러한 변환은 모든 사용자 인터페이스 요소에 적용할 수 있습니다. 다음은 변환 작업을 보여 주는 간단한 예제입니다.

</Button>
  <Button Content="여기를 클릭하십시오.">
   <Button.RenderTransform>
    <RotateTransform Angle="45" />
   </Button.RenderTransform>
  </Button>

RotateTransform 요소는 단추를 45도 회전시킵니다. 이 방법으로 단추를 회전시키는 것은 그다지 유용하지 않지만 이러한 기능이 있다는 것만으로 WPF 디자인의 다양성을 짐작할 수 있습니다. 사용자 인터페이스의 여러 요소는 동일한 기술에 기반을 두고 있기 때문에 여러 가지 방법으로 결합될 수 있습니다.

WPF는 몇 가지 미리 정의된 효과를 제공합니다. 변환과 마찬가지로 이러한 효과도 Buttons, ComboBoxes 등 사용자 인터페이스의 다양한 요소에 적용할 수 있습니다. 미리 정의된 효과로는 인터페이스 요소를 흐릿하게 표시하는 흐리게 효과, 요소를 빛나게 만드는 외부 글로우 효과, 인터페이스 요소 뒤에 그림자를 추가하는 그림자 효과 등이 있습니다.

애니메이션

인터페이스의 요소를 움직이게 만드는 애니메이션을 사용하면 여러 가지로 매우 유용합니다. 예를 들어 단추를 클릭할 때 단추가 실제로 눌린 것처럼 아래로 내려갔다가 다시 올라오면 훨씬 실감나는 인터페이스를 연출할 수 있습니다. 이보다 복잡한 애니메이션을 사용하여 사용자의 주의를 끌거나 이야기를 들려주는 방법으로 사용자의 참여를 유도하는 인터페이스를 만들 수 있습니다. WPF의 애니메이션 기능은 이러한 모든 효과를 지원합니다.

변환과 마찬가지로 애니메이션을 단추, 모양, 이미지 등 사용자 인터페이스의 다양한 요소에 적용할 수 있습니다. 애니메이션은 시간 흐름에 따라 개체의 속성 중 하나 이상의 속성 값을 변경하여 만듭니다. 예를 들어 EllipseHeight 속성 값을 2초 동안 조금씩 줄이면 타원이 천천히 찌그러지는 것처럼 보일 수 있습니다.

서로 관련된 애니메이션 그룹을 정의하면 유용할 수 있습니다. WPF에서 제공하는 Storyboard 클래스를 사용하면 이러한 작업을 할 수 있습니다. 각 Storyboard는 하나 이상의 '시간 표시 막대'를 포함할 수 있고, 각 시간 표시 막대는 하나 이상의 애니메이션을 포함할 수 있습니다. 제공되는 다양한 시간 표시 막대를 사용하면 애니메이션을 순차적으로 실행하거나 병렬로 실행할 수 있습니다. 다음은 Ellipse를 찌그러뜨리는 애니메이션을 보여 주는 간단한 XAML 예제입니다.

    <Ellipse Width="100" Height="50" Fill="Blue"
     Name="EllipseForSquashing">
     . . . 
     <Storyboard>
      <DoubleAnimation
       Storyboard.TargetName="EllipseForSquashing" 
       Storyboard.TargetProperty="Height"
        From="50" To="25" Duration="0:0:2" />
       </Storyboard>
       . . . 
    </Ellipse>      

앞에서 살펴본 예제에서와 마찬가지로 이 예제 역시 먼저 Ellipse를 정의합니다. 이 예제에서는 Name 속성도 함께 사용하여, 나중에 이 이름으로 Ellipse를 참조할 수 있도록 했습니다. 이 예제에는 몇 가지 세부 사항이 생략되었지만 XAML로 애니메이션을 정의하려면 Storyboard 요소가 반드시 있어야 합니다. 이 경우에는 EllipseHeight 속성이 Double 형식이기 때문에 StoryboardDoubleAnimation 요소가 들어 있습니다. 이 요소는 애니메이션을 만들 Ellipse의 이름, 변경할 속성 및 변경할 내용을 지정합니다. 이 예제에서는 Height의 값을 2초 동안 50에서 25로 변경합니다.

이 예제보다 훨씬 복잡한 애니메이션을 만들 수 있습니다. 예를 들어 애니메이션을 마우스 클릭 같은 이벤트를 통해 트리거하거나, 일시 중지했다가 다시 재생하거나, 지정한 횟수만큼(또는 계속) 반복하는 등 복잡한 애니메이션도 만들 수 있습니다. 애니메이션을 통해 개발자는 더 실감나고 사용하기 쉬우면서 보다 많은 기능을 제공하는 사용자 인터페이스를 만들 수 있습니다.

데이터 바인딩

대부분의 사용자 인터페이스는 특정한 유형의 데이터를 표시합니다. 인터페이스 개발자는 데이터 바인딩을 통해 데이터를 더 쉽게 표시할 수 있습니다. 데이터 바인딩을 사용하면 WPF 컨트롤에 표시되는 요소를 해당 컨트롤 외부에 있는 데이터와 직접 연결할 수 있습니다. 예를 들어 WPF TextBox 컨트롤의 Text 속성 값을 이 응용 프로그램의 비즈니스 논리의 일부인 Employee 개체의 Name 속성에 바인딩할 수 있습니다. 두 속성 중 하나가 변경되면 바인딩된 다른 한 속성에 해당 변경 내용이 반영됩니다. 예를 들어 사용자가 TextBox에서 값을 변경하면 Employee 개체의 Name 속성에도 변경된 값이 적용되고, 그 반대의 경우도 마찬가지로 적용됩니다.

두 개체의 속성 간에 이러한 연결을 만들려면 WPF Binding 클래스를 사용해야 합니다. 다음은 이러한 바인딩을 보여 주는 간단한 XAML 예제입니다.

<TextBox . . . >
 <TextBox.Text>
  <Binding Path="Name" />
 </TextBox.Text>
</TextBox>

이 예제에서는 Binding 요소의 Path 특성을 사용하여 TextBoxText 속성을 바인딩할 대상 속성을 식별합니다. Path는 이 속성이 속해 있는 개체(런타임에 지정됨)가 C# 또는 Visual Basic 등의 언어로 정의된 CLR(공용 언어 런타임) 개체인 경우에 사용됩니다. WPF의 데이터 바인딩 기능을 사용하면 CLR 개체는 물론 BindingXPath 속성을 사용하여 XML 데이터에 직접 연결할 수도 있습니다. 이 옵션은 지정한 데이터를 참조하는 XML 문서에서 하나 이상의 노드를 선택하는 XPath 쿼리를 만듭니다.

더 복잡한 데이터 바인딩 옵션을 사용할 수도 있습니다. 예를 들어 목록 바인딩을 사용하면 표준 IEnumerable 인터페이스를 구현하는 CLR 개체를 통해 ListBox 컨트롤에 내용을 채울 수 있습니다. 필요한 경우 데이터를 표시하기 전에 필터링 또는 정렬을 적용할 수도 있습니다. WPF에서는 ADO.NET Dataset에 바인딩할 수 있지만 관계형 데이터베이스 관리 시스템의 데이터에 직접 바인딩하는 기능은 지원하지 않습니다. 어떤 데이터 바인딩 옵션을 사용하는지에 관계없이 기본적으로 데이터 바인딩은 최대한 간단하게 사용자 인터페이스에 데이터를 표시하는 데 필요한 기능입니다.

사용자 인터페이스 자동화

WPF 인터페이스의 가장 일반적인 사용자는 당연히 사람입니다. 그러나 사용자 인터페이스를 작동하는 주체가 사람이 아니라 다른 소프트웨어인 경우도 있습니다. WPF의 UI(사용자 인터페이스) 자동화를 사용하면 이러한 방식으로 인터페이스를 작동할 수 있습니다.

예를 들어 개발자가 인터페이스를 실행하는 자동화된 스크립트를 만들어야 한다고 가정해 보겠습니다. 이 경우 개발자는 UI 자동화 기능이 제공하는 프로그래밍 방식의 액세스를 통해 사람이 실행하는 것처럼 인터페이스를 작동시키는 스크립트를 만들 수 있습니다. UI 자동화는 인터페이스의 다양한 요소를 음성으로 읽어 주는 도구와 같은 내게 필요한 옵션 도구를 만드는 데도 유용합니다. UI 자동화를 사용하면 이러한 요소가 들어 있는 트리에서 각 요소를 프로그래밍 방식으로 하나씩 실행할 수 있기 때문에 이러한 종류의 도구를 만들 수 있는 것입니다.

WPF에서는 UI 자동화를 사용하기 위해 UI 자동화 트리를 만듭니다. 이 트리는 인터페이스의 각 요소를 나타내는 일련의 AutomationElement 개체로 구성됩니다. 이 트리의 루트는 Desktop이고, 열려 있는 각 응용 프로그램은 이 루트의 자식이 됩니다. 트리는 각 응용 프로그램으로 세분화되고 각 WPF 컨트롤은 AutomationElement 개체 하나로 표시되거나, 경우에 따라 둘 이상의 개체로 표시됩니다. 이 경우 프로그래밍 방식으로 인터페이스에 액세스할 수 있도록 사용자가 상호 작용할 수 있는 모든 요소가 고유한 AutomationElement로 나타납니다. 예를 들어 단추가 여러 개 포함된 컨트롤에는 컨트롤 자체와 각각 고유한 AutomationElement 개체로 표시되는 단추가 모두 있습니다. 이와 같이 세분화된 UI 자동화 트리를 만들면 테스트 스크립트, 내게 필요한 옵션 도구 등의 클라이언트 응용 프로그램이 인터페이스의 각 구성 요소를 사람이 실제 사용하는 것처럼 액세스할 수 있습니다.

UI 자동화가 WPF의 핵심적인 기능은 아니며 대다수의 일반 사용자들은 이 기능을 거의 사용하지 않을 수도 있습니다. 그러나 소프트웨어 테스트 담당자나 움직임이 불편한 사용자와 같이 이를 필요로 하는 사용자들에게는 '없어서는 안 될' 중요한 기능입니다. 다수의 사용자들이 사용하는 기능만 중요한 것은 아닙니다.

Windows Presentation Foundation 적용

WPF에는 방대한 양의 기술이 포함되어 있습니다. 이러한 모든 기술이 사용자와의 상호 작용과 관련이 있지만 가장 많이 적용되는 세 가지 영역으로는 독립 실행형 WPF 응용 프로그램, XBAP 및 XPS 문서가 있습니다. 이 섹션에서는 이 세 가지 영역을 자세하게 살펴봅니다.

독립 실행형 WPF 응용 프로그램

WPF를 사용하는 가장 일반적인 방법은 독립 실행형 응용 프로그램에 사용하는 것입니다. 독립 실행형 WPF 응용 프로그램은 다른 일반적인 Windows 응용 프로그램처럼 실행되며 웹 브라우저를 사용하지 않습니다. 이러한 이유로 독립 실행형 응용 프로그램에는 완전한 신뢰 수준이 부여되고 WPF의 모든 기능을 사용할 수 있습니다. 완전 신뢰란 독립 실행형 WPF 응용 프로그램이 컴퓨터에 설치되어 있는 WCF(Windows Communication Foundation) 등의 다른 서비스를 자유롭게 사용할 수 있음을 의미합니다.

다른 Windows 응용 프로그램과 마찬가지로 독립 실행형 WPF 응용 프로그램을 로컬 디스크 또는 네트워크 서버에서 설치할 수 있으며 .NET Framework의 기능인 ClickOnce를 사용하여 설치할 수도 있습니다. ClickOnce는 사용자가 Internet Explorer를 통해 Windows 응용 프로그램(WPF 응용 프로그램 포함)을 다운로드하여 설치한 후 해당 응용 프로그램의 업데이트가 릴리스될 때 이를 자동으로 설치할 수 있게 해 주는 간단한 방법을 제공합니다.

XAML 브라우저 응용 프로그램: XBAP

독립 실행형 WPF 응용 프로그램이 대부분의 기능을 제공하지만 모든 경우에 적합한 것은 아닙니다. 클라이언트를 Windows 응용 프로그램으로 실행하는 것보다 웹 브라우저에서 실행하는 것이 더 적절한 경우도 많이 있습니다. WPF는 이러한 클라이언트에서도 최신 사용자 인터페이스를 사용할 수 있도록 XBAP를 제공합니다.

다음 그림에서 볼 수 있는 것처럼 XBAP는 Internet Explorer에서 실행됩니다. XBAP는 ASP.NET, JSP(JavaServer Pages) 및 기타 웹 기술을 사용하여 만든 웹 응용 프로그램의 클라이언트로 동작합니다. XBAP는 HTTP 또는 SOAP를 사용하여 이러한 웹 응용 프로그램과 통신할 수 있습니다. XBAP는 서버 플랫폼에 관계없이 항상 ClickOnce를 통해 로드되며 이 과정에서 사용자에게 대화 상자나 메시지를 전혀 표시하지 않고 일반적인 웹 페이지처럼 로드됩니다. 이러한 이유로 XBAP는 시작 메뉴나 프로그램 추가/제거에 표시되지 않습니다.

그림 7. Internet Explorer에서 실행되는 XBAP

일반적으로 XBAP는 탐색 형식의 인터페이스를 제공하지만 이는 선택 사항입니다. 탐색 형식의 인터페이스를 사용하면 사용자에게 익숙한 기존의 웹 클라이언트처럼 응용 프로그램을 실행할 수 있습니다. Internet Explorer 7에서는 XBAP가 브라우저의 기본 앞으로/뒤로 단추를 사용하고, 사용자가 액세스하는 XAML 페이지는 브라우저의 기록 목록에 나타납니다. 그러나 Internet Explorer 6에서는 XBAP가 자체적인 앞으로/뒤로 단추와 별도의 기록 목록을 사용합니다. XBAP는 현재의 실행 환경을 자동으로 파악하여 적절한 방식으로 동작하기 때문에 개발자는 개별 브라우저별로 버전을 만들지 않아도 됩니다.

XBAP는 웹에서 로드되어 브라우저에서 실행되기 때문에 .NET Framework의 코드 액세스 보안 기능이 부여하는 제한된 신뢰 수준에서만 실행됩니다. 이러한 이유 때문에 독립 실행형 WPF 응용 프로그램에서 사용할 수 있는 기능 중 일부를 XBAP에서는 사용하지 못할 수 있습니다. 예를 들어 인터넷 영역에서 배포된 XBAP에서는 다음과 같은 기능을 사용할 수 없습니다.

  • 독립 실행형 창 만들기
  • 응용 프로그램에서 정의한 대화 상자 표시
  • XBAP 자체에서 시작한 저장 대화 상자 표시
  • 제한적으로 사용할 수 있는 격리된 저장소 영역 이외의 파일 시스템에 액세스
  • UI 자동화 클라이언트로 동작
  • WCF 사용. WCF 응용 프로그램을 사용하려면 완전 신뢰 수준이 필요하기 때문에 인터넷에서 배포된 XBAP는 이 응용 프로그램을 사용할 수 없습니다. 대신에 ASMX라고 하는 ASP.NET 웹 서비스를 사용하여 원래 로드된 위치의 웹 응용 프로그램과 통신할 수 있습니다.
  • Windows Forms, MFC(Microsoft Foundation Class) 또는 Win32 직접 호출을 통해 만든 사용자 인터페이스 코드 사용. 다음 섹션에서 설명하는 것처럼 독립 실행형 WPF 응용 프로그램은 이러한 모든 이전 기술과 상호 운용될 수 있지만 신뢰 수준이 제한된 XBAP 환경에서는 여기에 나열된 기술 중 어떤 것도 사용할 수 없습니다.
  • 비관리 코드 사용

앞에서 살펴본 것처럼 독립 실행형 WPF 응용 프로그램 및 XBAP 모두에 동일한 코드 베이스를 사용할 수 있습니다. 이를 위해 개발자는 XBAP에서 사용할 수 없는 모든 기능을 ifdef에 래핑하여 조건부 컴파일을 사용할 수 있습니다. XBAP 버전에서는 문서 표시, 2차원 및 3차원 그래픽 사용, 비디오와 오디오 재생 등 독립 실행형 응용 프로그램 버전에서 사용할 수 있는 대부분의 기능을 동일하게 수행할 수 있을 뿐만 아니라 XBAP가 실행되고 있는 컴퓨터의 그래픽 하드웨어를 활용할 수도 있습니다.

Internet Explorer에는 XBAP뿐만 아니라 순수 XAML 페이지도 직접 표시할 수 있습니다. 'XAML 사용 완화'라고 하는 이러한 페이지는 브라우저에 정적 페이지를 표시할 때 유용합니다. 그러나 이벤트를 처리하려면 코드를 사용해야 하므로 결과적으로 XBAP를 만들어야 합니다.

개발자는 XBAP를 사용하여 브라우저 응용 프로그램에서 WPF 기능의 대부분을 사용할 수 있습니다. 또한 XBAP를 사용하면 독립 실행형 응용 프로그램과 브라우저 응용 프로그램에 코드가 거의 유사한 공통적인 프로그래밍 모델을 사용할 수 있습니다. 해당 클라이언트가 최신 Windows 플랫폼에서 실행되도록 디자인된 웹 응용 프로그램의 경우에는 XBAP를 사용하는 것이 좋습니다.

XPS 문서

XPS 문서는 WPF 환경에 사용되는 고정된 형식의 문서로, 사용자 인터페이스에서 매우 중요한 역할을 합니다. 앞에서 살펴본 것처럼 WPF는 DocumentViewer 컨트롤을 사용하여 XPS 문서를 표시합니다. 이 컨트롤을 WPF에 포함해야 하는 이유는 쉽게 이해할 수 있지만 XPS 자체를 WPF의 일부로 간주해야 하는 이유는 납득하기 어렵습니다. 실제로 XPS 사양에는 고정된 형식의 문서를 정의하기 위한 상당히 구체적인 방법이 명시되어 있으며, 이러한 문서는 다양한 방법으로 사용될 수 있습니다. 반면, WPF의 다른 모든 기능은 사용자 인터페이스를 만드는 데만 초점이 맞춰져 있습니다. 이와 같은 특징을 고려할 때 사용 범위가 더 넓은 XPS를 WPF라는 틀 안에 포함하는 것에 의문이 생길 수 있습니다.

XPS를 WPF의 일부로 보는 한 가지 중요한 이유는 XPS 문서가 XAML을 사용하여 정의된다는 점입니다. 레이아웃을 지정하는 Canvas 요소, 텍스트를 나타내는 Glyphs 요소, 2차원 그래픽을 만드는 Path 요소 등을 포함하여 XAML의 일부만 제한적으로 사용되지만 사실상 모든 XPS 문서는 XAML 문서입니다. 이 점을 고려하면 XPS를 WPF의 일부로 볼 수도 있습니다.

그러나 화면 표시 사용자 인터페이스는 XPS가 제공하는 핵심적인 기능과는 여전히 거리가 멉니다. Windows Vista부터는 XPS가 Windows의 기본 인쇄 형식으로 사용됩니다. XPS는 페이지 설명 언어로 사용되기 때문에 XPS를 지원하는 프린터에서 XPS 문서를 직접 렌더링할 수 있습니다. 따라서 화면 작업에서 프린터 작업에 이르는 모든 과정에서 XAML이라는 단일 설명 형식을 사용할 수 있습니다. 또한 XPS는 Windows에서 사용하던 기존의 GDI 기반 인쇄 방식을 향상시키므로 투명도 및 그라데이션과 같은 고급 그래픽 효과를 보다 정확하게 인쇄할 수 있습니다.

XPS 문서에는 XAML을 비롯하여 다양한 형식의 이미지(JPEG, PNG, TIFF 및 WMPhoto), 글꼴 데이터, 문서 구조에 대한 정보 등의 이진 데이터가 포함될 수 있습니다. 또한 필요한 경우 W3C XML 서명 정의 및 X.509 인증서를 사용하여 XPS 문서에 디지털 서명을 추가할 수도 있습니다. 모든 XSP 문서는 어떤 정보를 포함하는지에 관계없이 OPC(Open Packaging Convention)에서 정의하는 형식으로 저장됩니다. OPC는 XPS나 XAML 문서뿐만 아니라 XML 문서를 구성하는 여러 요소 간의 관계 및 이들 요소가 표준 ZIP 형식으로 저장되는 방법 등을 지정합니다. Microsoft Office 2007에서는 XML 형식에도 OPC를 사용하기 때문에 이 두 가지 형식의 문서 간에는 어느 정도의 공통점이 존재합니다.

앞에서 설명했듯이 WPF 응용 프로그램 사용자는 WPF DocumentViewer 컨트롤을 통해 XPS 문서를 볼 수 있습니다. Microsoft에서는 다음 그림에서 볼 수 있는 것처럼 DocumentViewer 컨트롤을 기반으로 하는 XPS 뷰어 응용 프로그램도 제공합니다. 이 응용 프로그램을 사용하면 컨트롤과 마찬가지로 문서에서 한 페이지씩 이동하고, 텍스트를 검색하는 등의 작업을 할 수 있습니다. XPS 문서는 사용 범위가 Windows로 제한되지 않기 때문에 Microsoft에서는 Apple Macintosh 같은 다른 플랫폼에서도 사용할 수 있는 XPS 뷰어를 제공할 예정입니다.

그림 8. XPS 뷰어를 사용하면 XPS 문서를 한 번에 한 페이지씩 읽을 수 있습니다.

WPF는 개발자가 XPS 문서를 만들고 로드하고 조작하는 데 사용할 수 있는 API 집합을 제공합니다. WPF 응용 프로그램에서도 OPC 수준의 문서를 사용할 수 있기 때문에 일반화된 방식으로 XPS 문서, Office 2007 문서 등에 액세스할 수 있습니다. Microsoft Windows Workflow Foundation을 사용하여 만든 응용 프로그램에서도 이러한 API를 통해 XPS 문서를 사용하는 워크플로를 만들 수 있습니다.

WPF는 응용 프로그램에서 고정된 형식의 문서를 표시하고 사용할 수 있도록 허용함으로써 최신 사용자 인터페이스의 구성 요소를 WPF가 지향하는 일관된 환경에 통합합니다. Windows Vista에서는 이와 동일한 형식으로 문서를 인쇄할 수 있기 때문에 화면에 표시되는 내용과 인쇄된 용지에 표시되는 내용 간의 일관성이 향상됩니다. XSP 문서 형식이 사용자 인터페이스에서 가장 중요한 기술은 아닐 수도 있지만 광범위하게 사용되는 XPS를 통해 WPF 기술이 얼마나 포괄적으로 사용되는지 그 범위를 단적으로 알 수 있습니다.

Windows Presentation Foundation 도구

WPF는 개발자가 유용하게 사용할 수 있는 다양한 기능을 제공합니다. 아무리 강력한 기술도 유용한 도구가 없다면 효용성이 떨어질 수 있습니다. Microsoft에서는 WPF를 사용하는 개발자와 디자이너에 각각 맞추어 최적화된 도구를 제공합니다. 이 섹션에서는 이 두 가지 도구에 대해 간략하게 설명합니다.

개발자용: Visual Studio

Visual Studio는 소프트웨어 개발자를 위한 Microsoft의 주력 응용 프로그램입니다. WPF의 최초 릴리스에는 개발자가 WPF 응용 프로그램을 만드는 데 사용할 수 있는 Visual Studio 2005 확장 기능이 함께 제공될 예정입니다. Visual Studio의 다음 릴리스(코드 이름: "Orcas")에는 Visual Designer for WPF(코드 이름: "Cider") 등의 다른 기능도 추가될 것입니다. 개발자는 이 비주얼 도구를 사용하여 WPF 인터페이스를 그래픽 방식으로 만든 후 기본적인 XAML을 자동으로 생성시킬 수 있습니다. 공식 릴리스 날짜는 아직 발표되지 않았지만 Orcas는 2007년 중에 출시될 예정입니다.

디자이너용: Expression Interactive Designer

앞에서 살펴본 것처럼 WPF의 기본적인 목표는 사용자 인터페이스를 만드는 작업에 디자이너가 적극적으로 참여할 수 있는 작업 환경을 만드는 것입니다. 이와 같은 목표는 XAML을 통해 실현할 수 있지만 새 작업 환경에서 디자이너가 작업하는 데 사용할 수 있는 도구가 필요합니다. 이를 위해 Microsoft에서는 Expression Interactive Designer를 만들었습니다.

아래의 스크린 샷에서 볼 수 있는 것처럼 Expression Interactive Designer는 사용자가 편리하게 작업할 수 있도록 가장 일반적인 디자인 도구 인터페이스를 제공합니다. 그러나 Designer는 WPF 응용 프로그램용 인터페이스를 만드는 데만 초점을 두어 설계되었습니다. 실제로 이 도구의 인터페이스도 WPF를 사용하여 만든 것입니다. 예를 들어 아래 화면에서 오른쪽 상단에 표시되는 WPF 컨트롤 목록과 맨 아래의 그래픽 시간 표시 막대가 이러한 인터페이스에 해당됩니다. 이러한 모든 특징은 이 문서의 앞부분에서 설명한 WPF 기능을 그대로 구현한 것으로, 인터페이스 디자이너가 자유롭게 사용할 수 있도록 설계되었습니다. 이 도구를 사용하면 애니메이션은 물론 변환, 효과 등의 다양한 기능을 그래픽 방식으로 만들 수 있습니다. 디자이너의 작업 결과는 자동으로 생성되는 XAML 파일 형식으로 저장되어 나중에 Visual Studio로 가져올 수 있습니다.

그림 9. 디자이너는 Expression Interactive Designer에서 WPF 인터페이스(그림 8)를 만들 수 있습니다.

Expression Interactive Designer는 Microsoft Expression 제품군의 세 가지 제품 중 하나입니다. 나머지 두 제품은 표준 기반 웹 인터페이스를 만드는 도구인 Expression Web Designer와 벡터 및/또는 비트맵 이미지를 만드는 도구인 Expression Graphic Designer입니다. 이 세 가지 응용 프로그램 중에서 Expression Interactive Designer만 WPF 응용 프로그램용 사용자 인터페이스를 만드는 데만 초점을 두어 설계되었습니다. Expression Graphic Designer에서 인터페이스의 GIF 이미지를 만드는 것처럼 나머지 두 제품을 사용하여 사용자 인터페이스의 구성 요소를 만들 수도 있지만 이 둘은 WPF 전용 도구가 아닙니다. 날짜는 아직 발표되지 않았지만 모든 Expression 도구는 WPF의 릴리스 이후에 출시될 예정입니다.

Windows Presentation Foundation 및 기타 Microsoft 기술

대부분의 Microsoft 신기술과 마찬가지로 WPF는 Windows 작업 환경의 다른 영역에 영향을 줍니다. 그러나 WPF 기술이 다른 영역에 미치는 영향을 살펴보기 전에 알아야 할 것은 시스템에 WPF를 설치해도 Windows Forms, MFC 등과 같이 기존의 다른 기술을 사용하는 소프트웨어와의 충돌이 발생하지 않는다는 점입니다. 즉 .NET Framework 3.0을 지원하는 시스템용으로 작성하는 새 응용 프로그램의 인터페이스는 대부분 WPF를 사용하여 만들지만 이전 기술을 사용하는 응용 프로그램도 이전과 마찬가지로 계속 실행할 수 있습니다.

Windows Presentation Foundation과 Windows Forms

.NET Framework의 최초 릴리스 이후 Windows Forms는 수많은 응용 프로그램을 만드는 데 사용되어 왔으며 WPF가 릴리스된 이후에도 일부 응용 프로그램에는 Windows Forms가 계속 사용될 것입니다. 예를 들어 이전 버전의 Windows와 같이 WPF를 사용할 수 없는 시스템에서 실행해야 하는 모든 구성 요소의 사용자 인터페이스는 Windows Forms를 사용하여 만들게 됩니다. Windows Forms가 제공하는 광범위한 컨트롤 집합을 사용하려는 경우와 같이 새 응용 프로그램에서도 필요에 따라 WPF 대신 Windows Forms를 사용할 수도 있습니다.

WPF를 사용하여 만든 응용 프로그램에서도 Windows Forms의 기능 중 일부를 활용하는 것이 유용할 수 있습니다. 예를 들어 Windows Forms는 WPF에 비해 더 많은 수의 컨트롤 집합을 제공합니다. .NET Framework 버전 2.0에 포함된 DataGridView 컨트롤의 경우 WPF에는 이 컨트롤을 대체할 수 있는 컨트롤이 없으며, 타사에서 다른 여러 가지 용도로 만든 Windows Forms 컨트롤도 상당히 많습니다. 경우에 따라서는 WPF 응용 프로그램에 이러한 기존 컨트롤을 사용해야 할 수도 있습니다. 이와는 반대로 WPF에도 3D 그래픽, 애니메이션 등 Windows Forms에서는 제공하지 않는 많은 기능이 있습니다. 이 경우에는 기존의 Windows Forms 응용 프로그램에 WPF의 기능을 통합하는 것이 좋습니다.

이러한 상호 보완은 충분히 가능합니다. 즉, WPF 응용 프로그램에서 Windows Forms 컨트롤을 호스팅하고 Windows Forms 응용 프로그램에서 WPF 컨트롤을 호스팅할 수 있습니다. 이렇게 하면 사용자는 한 응용 프로그램에서 WPF 대화 상자 및 Windows Forms 대화 상자를 별다른 불편 없이 사용할 수 있습니다.

WPF 응용 프로그램에서는 WPF의 WindowsFormsHost 컨트롤을 사용하여 Windows Forms 컨트롤을 호스팅합니다. 컨트롤의 이름에서 알 수 있듯이 이 컨트롤은 Windows Forms 컨트롤을 호스팅하여 WPF 응용 프로그램에서 Windows Forms 컨트롤을 사용할 수 있게 해 줍니다. 이 컨트롤은 ActiveX 컨트롤도 호스팅할 수 있기 때문에 이전 기술을 사용하여 만든 기존의 대규모 라이브러리를 WPF 응용 프로그램에서 액세스할 수 있습니다. 마찬가지로 Windows Forms 응용 프로그램에서는 WPF 컨트롤, 패널 및 기타 요소를 호스팅할 수 있는 Windows Forms 컨트롤인 ElementHost 컨트롤을 사용합니다. 이러한 각각의 기술을 구현하는 도구에서도 Windows Forms와 WPF용으로 작성된 소프트웨어를 모두 사용할 수 있습니다. 즉 WPF용 Visual Designer를 사용하여 Windows Forms 컨트롤을 배치하고, 마찬가지로 Windows Forms 디자이너를 사용하여 WPF 컨트롤을 배치할 수 있습니다.

그러나 WPF와 Windows Forms를 함께 사용할 경우 몇 가지 제한 사항도 있습니다. 예를 들어 WPF 컨트롤을 Windows Forms 컨트롤 위에 배치할 수는 없습니다. Windows Forms 컨트롤은 항상 최상위 계층에서 사용됩니다. WPF의 투명 효과나 변환 기능은 Windows Forms 컨트롤에 사용할 수 없습니다. 또한 WindowsFormsHostElementHost 컨트롤을 사용하려면 완전한 신뢰 수준이 필요하기 때문에 이러한 컨트롤을 사용하는 WPF 응용 프로그램을 XBAP로 실행할 수 없습니다. 그러나 대부분의 Windows 응용 프로그램의 사용자 인터페이스는 WPF와 Windows Forms를 함께 사용하여 만들 수 있습니다.

Windows Presentation Foundation과 Win32/MFC

2002년 .NET Framework가 출시되기 전에는 일반적으로 Windows 개발자가 Win32 API를 직접 호출하거나, 이 API를 래핑할 수 있는 C++ 래퍼를 제공하는 MFC를 사용하여 사용자 인터페이스를 만들었습니다. 따라서 이 방식으로 만든 인터페이스의 코드는 지금까지도 많이 사용되고 있습니다. WPF 환경에서는 이 코드가 어떻게 사용될까요?

이 질문에 대한 대답은 Windows Forms의 경우와 유사합니다. 즉, 기존 Win32/MFC 코드에서 WPF 컨트롤을 호스팅하는 것이 가능하고, WPF에서 기존 Win32/MFC 컨트롤을 호스팅하는 것도 가능합니다. 실제로 WPF와 Windows Forms 간의 상호 운용에 사용되는 기능은 Win32/MFC 상호 운용성 서비스를 기반으로 만들어졌습니다. WPF에서는 WPF 환경에서 Win32/MFC 컨트롤을 사용하는 데 필요한 HwndHost 클래스와 Win32/MFC 응용 프로그램에서 WPF 컨트롤을 사용하는 데 필요한 HwndSource 클래스를 제공합니다. 각 클래스는 필요에 따라 두 기술을 매핑합니다. 예를 들어 HwndHost는 Win32/MFC 컨트롤을 참조하는 데 사용되는 hWnd를 WPF 컨트롤인 것처럼 표시하고, 반대로 HwndSource는 WPF 컨트롤을 hWnd인 것처럼 표시합니다.

그러나 Windows Forms의 경우와 마찬가지로 이 두 환경을 함께 사용하는 경우에도 몇 가지 제약이 따릅니다. 실제로 Windows Forms 상호 운용성은 HwndHostHwndSource를 기반으로 하기 때문에 레이어 및 투명 효과에 대한 제약 등과 같이 앞에서 Windows Forms 컨트롤에 대해 설명한 모든 제한 사항이 이 경우에도 동일하게 적용됩니다. 또한 Windows Forms와는 달리 WPF와 Win32/MFC 코드를 함께 사용하는 응용 프로그램에서는 WPF의 관리 코드 환경과 Win32의 비관리 코드 환경 간의 상호 운용으로 인한 문제도 발생합니다. 이와 같은 모든 이유 때문에 Win32/MFC 코드를 사용하는 WPF 응용 프로그램은 XBAP로 실행할 수 없습니다. 그러나 앞에서 설명한 것과 마찬가지로 중요한 것은 Windows 응용 프로그램에서 WPF와 Win32/MFC를 함께 사용할 수 있다는 사실입니다. 즉, WPF를 사용하더라도 응용 프로그램의 기존 사용자 인터페이스 코드를 모두 버릴 필요는 없습니다.

Windows Presentation Foundation과 Direct3D

Direct3D는 Microsoft DirectX API 제품군의 일부로, 3차원 그래픽을 만드는 Windows 개발자들이 주로 사용하는 제품으로서 WPF가 출시된 이후에도 독자적인 가치를 제공할 것입니다. 앞에서 설명한 것처럼 실제로 WPF는 Direct3D를 통해 모든 렌더링 작업을 수행합니다. WPF의 출시 이후에 달라지는 것은 이제는 WPF에서도 3D 그래픽을 만들 수 있기 때문에 3D 개발자들이 둘 중 하나를 선택해야 한다는 점입니다.

그러나 이러한 결정은 비교적 쉽게 내릴 수 있을 것입니다. 고도의 과학적 시각화가 요구되는 3D 중심의 기술적인 응용 프로그램, 게임 등과 같이 3D를 집중적으로 개발해야 하는 경우에는 Direct3D를 사용하는 것이 좋습니다. WPF는 이러한 유형의 소프트웨어를 개발하기 위해 디자인된 플랫폼이 아니므로 적어도 WPF의 초기 릴리스는 이러한 용도로 사용하기에 적합하지 않습니다.

대신 WPF를 사용하면 전문적인 지식이 없는 일반 사용자들도 비교적 쉽게 3D 그래픽을 만들 수 있습니다. 또한 WPF 환경에서는 XBAP를 통해 웹에서 3D 그래픽을 사용할 수 있을 뿐만 아니라 2차원 그래픽과 문서를 비롯하여 응용 프로그램 사용자 인터페이스의 다른 여러 요소에 3D 그래픽을 통합할 수 있습니다. 앞에서 살펴본 HwndHost 클래스를 통해 WPF 응용 프로그램에서 Direct3D 코드를 호스팅할 수도 있습니다. WPF와 Direct3D는 각자 독자적인 가치를 제공하며 앞으로도 Windows 플랫폼에서 중심적인 기능을 할 것입니다.

Windows Presentation Foundation과 AJAX/"Atlas"

개발자는 AJAX를 사용하여 응답 성능이 뛰어난 브라우저 클라이언트를 만들 수 있습니다. AJAX를 사용하면 요청이 있을 때마다 페이지를 새로 고치지 않고도 응용 프로그램과 상호 작용할 수 있기 때문에 웹 브라우저와 웹 서버 사이의 데이터 교환 작업을 줄일 수 있습니다. AJAX는 브라우저에서 지원하는 XMLHttpRequest 개체를 사용하여 이 기능을 제공합니다. 이러한 개념은 1990년대 후반 Internet Explorer 5.0에 처음 소개되었으며 2000년대 중반에 이르러서는 더 많은 브라우저에서 XMLHttpRequest를 지원하게 되었고 AJAX가 보편화되었습니다.

그러나 AJAX 클라이언트를 만드는 작업은 그리 간단하지 않습니다. Microsoft는 이 작업을 위해 "Atlas"라는 코드 이름의 기술 집합을 만들었습니다. Atlas는 AJAX 응용 프로그램을 만드는 데 사용할 수 있는 라이브러리, 컨트롤 및 기타 요소의 집합으로, Internet Explorer뿐 아니라 다른 여러 브라우저에 사용할 수 있는 클라이언트 스크립트 라이브러리 및 서버 쪽에서 사용할 수 있는 ASP.NET 확장 기능으로 구성됩니다. Atlas는 AJAX 클라이언트가 포함된 웹 응용 프로그램을 보다 간단하게 만들 수 있도록 도와 줍니다.

AJAX는 다양한 브라우저에서 사용할 수 있다는 점에서 많은 개발자들이 관심을 갖는 기술입니다. AJAX를 사용하면 보다 뛰어난 대화형 인터페이스를 만들어 웹 사용자에게 제공할 수 있지만 지원되는 콘텐츠 형식이 매우 제한적이라는 단점이 있습니다. 예를 들어 AJAX만으로는 그래픽, 비디오, 애니메이션 및 기타 최신 상호 작용 방식을 지원할 수 없습니다. 따라서 해당 클라이언트에서 WPF를 지원하도록 해야 하는 응용 프로그램을 만들려면 AJAX 대신 XBAP를 선택하는 것이 좋습니다.

Windows Presentation Foundation과 "WPF/E"

XBAP를 사용하면 웹 응용 프로그램에서 WPF 기능의 대부분을 구현할 수 있지만 이를 위해서는 클라이언트 컴퓨터에 WPF가 설치되어 있어야 하므로 웹 응용 프로그램의 사용 범위가 제한될 수 있습니다. 또한 WPF를 지원하지 않는 Macintosh나 기타 시스템에서도 액세스할 수 있고 최신 인터페이스를 제공하는 웹 응용 프로그램을 만들어야 하는 경우가 생길 수도 있습니다.

코드 이름 "WPF/E"는 이와 같은 문제를 해결하기 위해 곧 제공될 기술입니다. WPF/E("E"는 Everywhere를 나타냄)는 Macintosh와 같은 다양한 클라이언트 플랫폼, 소형 장치 등을 비롯하여 Internet Explorer, FireFox, Netscape 등의 다양한 웹 브라우저에 WPF의 기능 중 일부를 제공할 예정으로, 여기에는 2차원 그래픽, 이미지, 비디오, 메모 및 텍스트가 포함됩니다. 그러나 XBAP에서 지원하는 기능 중 3차원 그래픽, 문서, 하드웨어 가속 등의 일부 기능은 WPF/E에서 지원되지 않습니다.

개발자는 JavaScript를 사용하여 WPF/E 응용 프로그램을 만들 수 있습니다. C# 및 Visual Basic 언어를 사용하여 개발할 수 있도록 WPF/E에는 .NET Framework의 플랫폼 간 호환 기능 중 일부도 포함될 것입니다. WPF/E는 .NET Framework 3.0의 일부가 아니며 2007년 중에 릴리스될 것으로 예상됩니다. WPF/E가 릴리스되면 웹 응용 프로그램 작성자는 광범위한 플랫폼에서 다양한 기능을 사용하여 클라이언트 응용 프로그램을 만들 수 있는 또 다른 기술을 경험할 수 있을 것입니다.

결론

사용자 인터페이스는 대부분의 응용 프로그램에서 매우 중요한 부분을 차지합니다. 효과적인 인터페이스를 만들면 사용자 및 사용자가 속한 조직에 상당한 이점을 제공할 수 있습니다. WPF의 기본적인 목표는 개발자가 이러한 효과적인 사용자 인터페이스를 만들 수 있도록 돕는 것이기 때문에 WPF는 Windows 응용 프로그램을 만드는 개발자나 일반 사용자 모두가 기대할 만한 기술입니다.

WPF는 최신 사용자 인터페이스를 만들기 위한 통합 플랫폼을 제공하고, 이러한 인터페이스를 만드는 작업에 디자이너가 보다 적극적으로 참여할 수 있도록 도와 주며, 독립 실행형 응용 프로그램과 브라우저 응용 프로그램을 위한 공통적인 프로그래밍 모델을 제공함으로써 Windows 사용자 환경을 크게 향상시키는 것을 목표로 합니다. WPF는 지난 20년 동안 Windows 사용자 인터페이스의 기반이 되어 온 기술을 대체하는 새로운 기술을 제시하여 향후 20년 동안 사용할 기반 기술로서의 역할을 할 것입니다.

1.     WCF 서비스를 구동시키기

-       서비스를 담당할 전담 웹사이트 프로젝트를 만듭니다.


-       저장 위치를 지정하고, WCF 서비스 항목을 선택합니다.


-       App_Code폴더와 그 안에 IService.cs, Service.cs 파일 그리고, Service.svc 파일이 자동 생성된 것을 볼 수 있는데, 서비스 구현은 이미 했기 때문에 Service.svc파일을 제외한 두 개의 파일들을 과감하게 삭제 해버립니다.


-       참조 추가 항목을 선택하고, WCF서비스 라이브러리 프로젝트 항목을 선택합니다. 그리고, Bin 폴더에 dll이 잘 추가된 것을 볼 수 있습니다.

 

-       Service.svc 파일을 수정합니다.

자동 생성되었던 Service.svc

<%@ ServiceHost Language="C#" Debug="true" Service="Service" CodeBehind="~/App_Code/Service.cs" %>

 

수정된 Service.svc

<%@ ServiceHost Debug="true" Language="C#" Service="WCFServiceLibrary.ProductService" %>

ð  기존 파일에는 Service태그에 클래스명을 지정되어 있고, CodeBehind에 해당 코드 주소를 입력하였으나, 별도의 컴포넌트로 구현하였기에, 컴포넌트 이름에 해당 서비스 클래스명을 지정해 주면 됩니다.

-       Web.config 수정하여야 하는데, 전에 app.config 파일을 WCF 구성 편집 항목을 통해 수정해 본 적이 있습니다. 그 방식과 같이 WCF서비스 구성을 편집합니다. (9번 항목)

-       Web.config 파일을 열어 보면 <system.serviceModel>부분을 제외하고 나머지는 과감하게 삭제해버립니다.

Web.config

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <system.serviceModel>

    <behaviors>

      <serviceBehaviors>

        <behavior name="ServiceBehavior">

          <serviceMetadata httpGetEnabled="true" />

          <serviceDebug includeExceptionDetailInFaults="false" />

        </behavior>

      </serviceBehaviors>

    </behaviors>

    <services>

      <service behaviorConfiguration="ServiceBehavior" name="WCFServiceLibrary.ProductService">

        <endpoint address="" binding="basicHttpBinding" bindingConfiguration=""

          contract="WCFServiceLibrary.IProductService">

          <identity>

            <dns value="localhost" />

          </identity>

        </endpoint>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />

      </service>

    </services>

  </system.serviceModel>

</configuration>

-       WCFServiceWebSite 웹사이트의 속성에 가상 경로가 “/”가 아닌 다른 경로가 지정된 경우가 있는데, “/”로 수정합니다. 조금 있다 알게 되겠지만, 정책 파일을 찾는 경로는 웹사이트 최상위 루트이기 때문에 바꿔주어야 합니다.

 

-       Service.svc브라우저에서 보기 항목을 선택하여 잘 구동되는지를 확인합니다.


-       WCF 테스트 브라우저 창을 통해 WCF 서비스 역할이 잘 작동하는지 확인한 적이 있습니다. 웹사이트에서도 잘 되는지 확인하겠습니다. Visual Studio 2008 명령 프롬프트를 선택하고, cmd창이 나타나는 것을 볼 수 있습니다. (cmd창에서 Visual Studio 2008 설치 경로\VC로 들어가시면 됩니다. 기본 설치시 C:\Program Files\Microsoft Visual Studio 9.0\VC 입니다.)


-       좀 전에 svc 파일을 브라우저에서 봤었는데, cmd창에 명령어를 “wcfTestClient + 브라우저에서 봤던 url”를 입력하시면 WCF 테스트 브라우저 창이 나타나며, 전에 했던 방식으로 서비스 역할 테스트를 해보시면 됩니다. (부가 설명은 하지 않겠습니다.)


2.     Silverlight 응용 프로그램 만들기 (위에서 설명한 바가 있어, 자세한 설명은 하지 않겠습니다)

-       솔루션에 새 프로젝트 추가 한 후, 프로젝트명과 저장 경로를 지정하고, Silverlight 응용 프로그램을 선택합니다.

-       Silverlight를 호스팅할 웹 사이트 지정하는 브라우저 창이 나타나며, WCFServiceWebSite WCF 서비스 전담으로 만든 프로젝트이므로, “솔루션에 Silverlight를 호스팅할 새 ASP.NET 웹 프로젝트 추가항목을 선택하여 웹 사이트를 추가합니다.

-       Silverlight 영역에 DataGrid 컨트롤 및 각 이벤트의 버튼을 추가하여 UI을 구상합니다. Microsoft Blend2를 실행시켜 디자인 작업하면 손쉽게 진행할 수 있습니다.

Code

Page.xaml

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="SilverlightApplication.Page"

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

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

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.RowDefinitions>

            <RowDefinition Height="60"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

        </Grid.RowDefinitions>

       

<StackPanel Orientation="Horizontal" Grid.Row="0">

            <Button x:Name="btnSelect" Width="60"  Height="35" Margin="5" Content="보기"></Button>

            <Button x:Name="btnInsert" Width="60"  Height="35" Margin="5" Content="추가"></Button>

            <Button x:Name="btnUpdate" Width="60"  Height="35" Margin="5" Content="수정"></Button>

            <Button x:Name="btnDelete" Width="60"  Height="35" Margin="5" Content="삭제"></Button>

        </StackPanel>

<data:DataGrid Grid.Row="1"></data:DataGrid>

    </Grid>

</UserControl>

-       Silverlight 응용 프로젝트에 WCF 서비스를 참조합니다. 좀전에 WCF 서비스 전담 웹사이트에서의 svc 파일 URL을 주소에 입력하고 이동하면, 문제가 없다면 인터페이스 목록이 나타납니다. 그리고 서비스 참조 네임스페이스를 입력하고 추가합니다.


-       UI 구성 및 서비스 참조가 완료한 후, 모든 버튼의 이벤트 함수를 구현하기에 앞 서, “보기 버튼에 대한 이벤트를 구현해보겠습니다.

Code

Page.xaml

<!-- 생략 -->

<StackPanel Orientation="Horizontal" Grid.Row="0">

    <Button x:Name="btnSelect" Width="60"  Height="35" Margin="5" Content="보기" Click="btnSelect_Click"></Button>

    <Button x:Name="btnInsert" Width="60"  Height="35" Margin="5" Content="추가" Click="btnInsert_Click"></Button>

    <Button x:Name="btnUpdate" Width="60"  Height="35" Margin="5" Content="수정" Click="btnUpdate_Click"></Button>

    <Button x:Name="btnDelete" Width="60"  Height="35" Margin="5" Content="삭제" Click="btnDelete_Click"></Button>

</StackPanel>

<data:DataGrid Grid.Row="1" x:Name="dlResult" Background="Beige"></data:DataGrid>

<!-- 생략 -->

 

Page.xaml.cs

public partial class Page : UserControl

{

    ProductDBService.ProductServiceClient serivce = new ProductDBService.ProductServiceClient();

 

    public Page()

    {

        InitializeComponent();

    }

 

    private void btnSelect_Click(object sender, RoutedEventArgs e)

    {

        serivce.SelectProductAsync();

        serivce.SelectProductCompleted += new EventHandler<SelectProductCompletedEventArgs>(serivce_SelectProductCompleted);

    }

 

    void serivce_SelectProductCompleted(object sender, SelectProductCompletedEventArgs e)

    {

        dlResult.ItemsSource = e.Result;

    }

 

    private void btnInsert_Click(object sender, RoutedEventArgs e) {  }

 

    private void btnUpdate_Click(object sender, RoutedEventArgs e) {  }

 

    private void btnDelete_Click(object sender, RoutedEventArgs e) {  }

}

Description

ð  WCF 서비스에 노출된 서비스를 보면, Async 함수와 Completed 이벤트를 가지게 되는 것을 볼 수 있습니다. 간단히 설명드리면, Async 함수로 필요한 인자를 넣고 실행시키면, Completed 이벤트 함수에서 Result(WCF 서비스 호출한 데이터)를 보내주는 방식입니다.


ð  DataList 컨트롤에 서비스 호출하여 Select한 데이터를 바인딩한 후, 잘 동작하는 지 실행(F5)합니다. 하지만, 아래와 같은 오류가 발생하는 것을 볼 수 있으며, IE 개발 툴인 HttpWatch, Fidder, WebDevHelper 등을 이용하여 조회하여 보면, 2개의 파일에서 404. 파일이 없다는 결과를 볼 수 있습니다.


ð  Silverlight는 크로스 도메인에 대해서 제약이 되어 있다고 설명한 바가 있습니다. 크로스 도메인 접근을 위해서는 웹사이트의 최상위 루트 디렉토리에 보안 정책 파일인 clientaccesspolicy.xml 파일과 crossdomain.xml 파일을 배포하여야 합니다.

(참고 : Silverlight 2.0 Tutorial)

-       보안 정책 파일을 WCF 서비스 웹사이트의 최상위 루트에 배포한 후, 다시 실행하면, 잘 작동하는 것을 볼 수 있습니다.


-       마지막으로 남은 버튼의 이벤트도 구현하겠습니다.

Code

public partial class Page : UserControl

{

    ProductDBService.ProductServiceClient serivce = new ProductDBService.ProductServiceClient();

 

    public Page()

    {

        InitializeComponent();

    }

 

    private void btnSelect_Click(object sender, RoutedEventArgs e)

    {

        serivce.SelectProductAsync();

        serivce.SelectProductCompleted += new EventHandler<SelectProductCompletedEventArgs>(serivce_SelectProductCompleted);

    }

 

    void serivce_SelectProductCompleted(object sender, SelectProductCompletedEventArgs e)

    {

        dlResult.ItemsSource = e.Result;

    }

 

    private void btnInsert_Click(object sender, RoutedEventArgs e)

    {

        Products product = new Products();

        product.ProductName = "TEST";

 

        serivce.InsertProductAsync(product);

        serivce.InsertProductCompleted += new EventHandler<InsertProductCompletedEventArgs>(serivce_InsertProductCompleted);

    }

 

    void serivce_InsertProductCompleted(object sender, InsertProductCompletedEventArgs e)

    {

        Refresh(e.Result);

    }

 

    private void btnUpdate_Click(object sender, RoutedEventArgs e)

    {

        serivce.UpdateProductAsync(dlResult.SelectedItem as Products);

        serivce.UpdateProductCompleted += new EventHandler<UpdateProductCompletedEventArgs>(serivce_UpdateProductCompleted);

    }

 

    void serivce_UpdateProductCompleted(object sender, UpdateProductCompletedEventArgs e)

    {

        Refresh(e.Result);

    }

 

    private void btnDelete_Click(object sender, RoutedEventArgs e)

    {

        serivce.DeleteProductAsync((dlResult.SelectedItem as Products).ProductName);

        serivce.DeleteProductCompleted += new EventHandler<DeleteProductCompletedEventArgs>(serivce_DeleteProductCompleted);

    }

 

    void serivce_DeleteProductCompleted(object sender, DeleteProductCompletedEventArgs e)

    {

        Refresh(e.Result);

    }

 

    private void Refresh(bool result)

    {

        if (result)

        {

            MessageBox.Show("작업 완료 되었습니다.");

            serivce.SelectProductAsync();

        }

        else

        {

            MessageBox.Show("작업 실패하였습니다.");

        }

    }

}

Description

ð  각 버튼의 이벤트를 구현하였으며, 추가, 수정, 삭제 시 리플래시하였습니다.

 

 

l  참고 사이트

-       MSDN Library (WCF)

http://msdn.microsoft.com/ko-kr/library/ms735119.aspx

 

1.     WCF 서비스 구현하기

-      이름을 넣고 WCF 서비스 항목을 선택하여 추가하면 App.config, ProductService.cs 그리고 인터페이스 IProductService.cs 파일이 자동 생성되어 있으며, 샘플 코드는 삭제합니다.

-       CRUD 기능 구현을 위해 인터페이스에 메서드 재정의를 선언합니다.

Code

IProductService.cs

[ServiceContract]
public interface IProductService
{
    [OperationContract]
    bool InsertProduct(Products product);

    [OperationContract]
    bool UpdateProduct(Products product);

    [OperationContract]
    bool DeleteProduct(string name);

    [OperationContract]
    List<Products> SelectProduct();
}

ð  인터페이스 IProductService.cs 상단 부분에 보면 [ServiceContract]이라는 속성이 명시되어 있습니다. WCF 응용 프로그램의 서비스 계약을 정의하는 것으로, 반드시 선언하여야 합니다.

ð  메서드 재정의 부분에 [OperationContract]이라는 속성이 명시되어 있으며, WCF 응용 프로그램의 서비스 계약의 일부인 작업을 정의합니다.

-       CRUD(Insert, Update, Delete, Select) 로직을 구현합니다.

Code

ProductService.cs

namespace WCFServiceLibrary

{

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class ProductService : IProductService

    {

        NorthwindDBDataContext dc = new NorthwindDBDataContext();

 

        public bool InsertProduct(Products product)

        {

            try

            {

                dc.Products.InsertOnSubmit(product);

                dc.SubmitChanges();

 

                return true;

            }

            catch { return false; }

        }

 

        public bool UpdateProduct(Products product)

        {

            try

            {

                var target = (from tmp in dc.Products

                              where tmp.ProductID == product.ProductID

                              select tmp).Single();

               

                target.ProductID = product.ProductID;

                target.ProductName = product.ProductName;

                target.SupplierID = product.SupplierID;

                target.CategoryID = product.CategoryID;

                target.QuantityPerUnit = product.QuantityPerUnit;

                target.UnitPrice = product.UnitPrice;

                target.UnitsInStock = product.UnitsInStock;

                target.UnitsOnOrder = product.UnitsOnOrder;

                target.ReorderLevel = product.ReorderLevel;

                target.Discontinued = product.Discontinued;

                dc.SubmitChanges();

 

                return true;

            }

            catch { return false; }

        }

 

        public bool DeleteProduct(string name)

        {

            try

            {

                var target = (from tmp in dc.Products

                              where tmp.ProductName.Equals(name)

                              select tmp).ToList();

 

                dc.Products.DeleteOnSubmit(target[0]);

                dc.SubmitChanges();

 

                return true;

            }

            catch { return false; }

        }

 

        public List<Products> SelectProduct()

        {

            var target = (from tmp in dc.Products

                          select tmp).ToList();

 

            return target;

        }

    }

}

ð  클래스 상단 부분에 [ServiceBehavior]이라는 속성이 명시되어 있으며, 서비스 계약 구현의 내부 실행 동작을 지정합니다. InstanceContextMode는 들어오는 메시지에 포함된 호출을 처리할 수 있는 서비스 인스턴스 수를 지정합니다. WCF 서비스 구현에 중요한 요소이므로 자세히 알아보겠습니다.

모드

설명

Single

개체가 들어오는 모든 호출에 대해 사용되며 호출 후에는 재활용되지 않습니다. 서비스 개체가 없는 경우 새로 만들어집니다. (공유개념)

PerCall

매번 호출하기 전에 만들어지고 매번 호출한 후에 재활용됩니다. 채널에서 세션을 만들지 않으면 이 값은 PerCall인 것처럼 동작합니다. (비동기인 Silverlight에서는 의미없는 모드라고 볼 수 있습니다.)

PerSession

각 세션마다 개체가 만들어집니다. (클라이언트가 더 이상 필요로 하지 않을 때까지 인스턴스가 존재합니다.)

ð  LINQ에 대한 MSDN Library 링크

2.    빌드(F6), App.config 파일 수정 (해당 기능 꼭 알아두기)

-       해당 파일을 열어 수정하는 방법도 있지만, WCF 구성 편집 항목을 이용하여 편집해보겠습니다.

-      App.config 파일에 마우스 오른쪽 버튼을 클릭하면 WCF 구성 편집 항목을 선택합니다.

-       WCF 구성 편집 창이 나타나며, WCF 서비스 라이브러리에 정의된 것과 같은지 확인합니다. 틀릴 경우 해당 항목을 선택하면 <!--[if !vml]--><!--[endif]-->이 나타나는데 클릭합니다. 그리고, bin폴더/Debug폴더 안에 WCFServiceLibrary.dll을 선택한 후, 알맞은 형식 이름을 선택하시면 자동으로 변경됩니다.

-       위 파트에서 설명한 바가 있지만, Silverlight에서는 바인딩을 basicHttpBinding만 지원하므로 반드시 변경해주여야 합니다.

-       그리고 Contact 속성이 맞게 지정되어 있는지 확인합니다. 틀릴 경우 위에서 했던 방식으로 알맞은 형식 이름을 선택합니다.

3.     WCF 서비스 구성이 잘 되어 작동이 이상유무를 확인해 봅니다.

-       실행(F5)를 해보면, 아래와 같이 WCF 테스트 클라이언트 창이 나타나며, 트라이아이콘에 WCF 서비스 호스트 아이콘이 나타나며 구성에는 이상없음을 나타냅니다.

-       SelectProduct()을 더블클릭 한 후, 별다른 인자가 특별 없기 때문에 우측에 호출 버튼을 클릭합니다. Length에 아마 NorthWind 데이터베이스의 Products테이블의 아이템 개수와 동일하게 나나타나는 것을 볼 수 있습니다.

-       이번에는 InsertProduct()을 더블클릭 한 후, 각 변수의 임의의 값을 넣어주고 호출을 하면 성공시, 응답 화면에 return 값에 true가 나타나며, DB 테이블에 아이템 개수가 한 개 늘어난 것을 볼 수 있습니다.

ü  WCF 서비스 라이브러리를 사용하여 WCF Service 만들기

1.     구현 설명

-       Linq to Sql 클래스를 통해 DB 서비스 구현

-       CRUD(Select, Insert, Update, Delete) 기능 구현

-       Silverlight DataGrid 컨트롤 추가하여 데이터 바인딩 및 CRUD 이벤트 구현

2.     WCF 서비스 라이러브리 프로젝트 추가하기

-       웹사이트에 Silverlight 사용 WCF 서비스 항목을 선택하여 서비스 구현하여도 상관없지만, 확장성 및 유지 보수를 고려해 볼 때, WCF 서비스 라이브러리 프로젝트로 서비스 구현하는 것이 관리하기 좋습니다.

-       WCF 서비스 라이브러리 항목을 선택 한 후, 새 프로젝트를 추가합니다.

-       IService1.cs Service1.cs, App.config 세 개의 파일이 생성되어 있는 것을 볼 수 있으며, 모두 삭제 한 후 새로 구현해 보겠습니다.

3.     “Northwind and pubs Sample Databases for SQL Server 2000” 를 다운 받아 샘플 데이터베이스 환경을 만듭니다.

-       링크 페이지에서 SQL2000SampleDb.msi 파일을 다운 받아 설치 합니다. (링크)

-       기본적으로 C:\SQL Server 2000 Sample Databases 아래 데이터 베이스 파일이 저장됩니다.

-       Microsoft SQL Server Studio를 열어, Northwind DB를 연결 추가합니다.

-      연결할 데이터 베이스 추가할 항목을 선택한 후, 추가합니다.

 =>

4.    LINQ to SQL 클래스 추가한 후, DB 연결 하기

-      WCF 서비스 라이브러리 프로젝트에 LINQ to SQL 클래스를 선택하고, 이름 작성한 후, 추가버튼을 클릭합니다.

-      아래와 같은 화면이 나타나며 서버 탐색기를 열어(메뉴에서 보기à서버 탐색기 혹은 Ctrl + W, L) 샘플 데이터 베이스(Northwind) 스키마를 추가합니다.

-      서버 탐색기에서 데이터 연결에 마우스 오른쪽 버튼을 클릭하면 연결 추가가 나오며, Microsoft SQL Server를 선택한 후, 계속 버튼을 클릭합니다.

 =>

-       연결할 서버 이름 및 데이터베이스 이름을 선택하며, 연결 테스트 버튼을 클릭한 후, “테스트 연결에 성공하였습니다.” 라는 성공 메시지가 나타나면 확인을 누릅니다.

5.     Northwind 데이터베이스 스키마가 추가된 것을 볼 수 있으며, 테이블 및 저장 프로시저를 볼 수 있습니다.

-       SQL Server 2005 Management Studio 에서의 기본적인 기능은 제공한다고 합니다.

(데이블 데이터 조회, 쿼리 디자이너, 저장 프로시저 작성)

6.     작업을 진행할 테이블 및 저장 프로시저를 오른쪽 화면으로 드래그하면 아래 화면과 같이 추가됩니다. 여러 개의 테이블을 사용할 경우에는 여러 개를 드래그하여 스키마를 관리하면 됩니다.

7.    속성 창을 열어 DataContext 정의 할 때, Serialization Mode None에서 Unidirectional으로 변경해 줍니다. (객체를 직렬화)

ü  WCF Service의 개념

1.     닷넷의 여러 분산 기술들을 하나로 통합하여 SOA기반의 애플리케이션을 쉽게 개발해 줄 수 있게 지원해주는 기술이며, 기존의 복잡했던 각각의 개발 방식을 일관된 방식으로 프로그래밍할 수 있게 제공해줍니다.

2.     보안이나 트랜잭션과 같은 기능을 구현할 수 있는 높은 생산성을 제공해주고 있고, 기존의 닷넷 분산 기술과 웹 서비스 확장 스펙(WS-*)과의 높은 상호 운용성을 제공해 주고 있습니다. , 닷넷 웹 서비스를 포함하여 좀 더 포괄적인 분산 기술을 지원한 닷넷 기술이라고 보시면 됩니다.

     참고 사이트

MSDN - WCF(Windows Communication Foundation) 서비스 구축

ü  Silverlight에서 WCF Service를 사용하는 경우

1.     DB에 접근할 때

-       Silverlight에서는 .NET의 데이터 처리(DataSet)가 지원하지 않습니다. 웹 서비스 및 WCF 서비스를 통해 데이터를 가져와야 합니다.

2.    다른 플랫폼과 소통을 위한 경우

3.     기타 외부에서 필요한 인자를 읽어오려 할 때

ü  Silverlight를 위한 WCF Service 만들기

1.     WCF의 가장 기본이 되는 개념인 엔드포인트(EndPoint)의 개념

-       WCF서비스와 클라이언트가 엔드포인트를 통해 메시지를 주고 받게 됩니다..

-      엔드포인트는 주소(Address), 바인딩(Binding), 계약(Contact) 3가지 요소로 구성되어 있습니다. , 어디에서(Where) 무엇을(What) 어떻게(How) 통신할 것인지에 대한 개념입니다.

2.   웹사이트에 WCF Service 만들기 방법

-       새로 만들기에 웹사이트를 새로 만듭니다.

-       WCF 서비스를 선택하고, 폴더 경로를 선택하여 프로젝트를 생성합니다.

-       App_Code폴더에 IService.cs Service.cs 두개의 파일이 생성되어 있는 것을 볼 수 있으며, 파일에 작성되어 있는 샘플 코드를 지우고 아래와 같이 작성합니다.

Code

IService.cs

[ServiceContract]

public interface IService

{

    [OperationContract]

    DateTime GetNowDate();

}

 

Service.cs

public class Service : IService

{

    public DateTime GetNowDate()

    {

        return DateTime.Now;

    }

}

-       Web.config을 열어보시면, EndPoint binding 속성을 basicHttpBinding으로 변경합니다.

Code

<!-- 중략 -->

<system.serviceModel>

    <services>

      <service name="Service" behaviorConfiguration="ServiceBehavior">

        <!-- Service Endpoints -->

        <endpoint address="" binding="basicHttpBinding" contract="IService">

          <!--

              배포 시 다음 identity 요소는 배포된 서비스를 실행할 때 사용하는 ID를 반영하도록

              제거되거나 대체되어야 합니다. 해당 요소가 제거되면 WCF에서는 적합한 ID

              자동으로 유추합니다.

          -->

          <identity>

            <dns value="localhost"/>

          </identity>

        </endpoint>

        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

      </service>

    </services>

    <behaviors>

      <serviceBehaviors>

        <behavior name="ServiceBehavior">

          <!-- 메타데이터 정보를 공개하지 않으려면 배포하기 전에 아래의 값을 false로 설정하고 위의 메타데이터 끝점을 제거하십시오. -->

          <serviceMetadata httpGetEnabled="true"/>

          <!-- 디버깅 목적으로 오류에서 예외 정보를 받으려면 아래의 값을 true로 설정하십시오. 예외 정보를 공개하지 않으려면 배포하기 전에 false로 설정하십시오. -->

          <serviceDebug includeExceptionDetailInFaults="false"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>

  </system.serviceModel>

</configuration>

Description

ð  Silverlight Web에 종속된 기술이기 떄문에 기본적인 바인딩인 basicHttpBinding만 지원합니다.

-      컴파일 후, Service.svc 파일을 브라우저에서 보기 하면 다음과 같은 화면이 나타나며, 제대로 작동하고 있다는 것을 알 수 있습니다. 이 서비스는 WCF 서비스이자 웹 서비스라 할 수 있습니다.

3.     Silverlight 에서 WCF Service 참조하기

-       Silverlight 응용 프로그램을 선택한 후, 새 프로젝트를 추가합니다.

-       WCF 서비스 프로젝트에서 결과를 확인할 수 있게 기존 웹 사이트에 연결합니다.

-       Silverlight 응용 프로젝트가 생성이 되면, 프로젝트 참조 부분에 오른쪽 마우스를 눌러 서비스 참조를 선택합니다. (이하, ASP.NET에 웹 서비스 참조 하는 방식과 유사합니다.)

-       좀전에 Service.svc URL를 주소에 넣고, 이동을 누르면 해당 서비스 목록이 나타나며, 서비스 네임스페이스명을 지정합니다.

-       서비스 참조된 것을 볼 수 있으며, 서비스 설정 파일(ServcieReferences.ClientConfig)이 생성된 것을 볼 수 있으며, ServcieReferences.ClientConfig 파일을 열어보면 WCF 서비스 설정이 생성된 것을 볼 수 있습니다.

Code

ServcieReferences.ClientConfig

<configuration>

    <system.serviceModel>

        <bindings>

            <basicHttpBinding>

                <binding name="BasicHttpBinding_IService" maxBufferSize="2147483647"

                    maxReceivedMessageSize="2147483647">

                    <security mode="None" />

                </binding>

            </basicHttpBinding>

        </bindings>

        <client>

            <endpoint address="http://localhost:8553/WCFService1/Service.svc"

                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService"

                contract="WCFService.IService" name="BasicHttpBinding_IService" />

        </client>

    </system.serviceModel>

</configuration>

ð  basicHttpBinding전송수준에서의 보안이나 메시지자체의 보안기능은 제공하지만, 트랙젼선이나 세션과 같은 기능은 제공하지 않습니다.

4.    WCF Service 호출하여 Silverlight에 데이터 결과를 보여주기

-       Page.xaml 파일에 데이터를 받기 위한 텍스트블록 컨트롤을 추가하고, 페이지 로드시, 서비스 호출하여 화면에 보여줍니다.

Code

Page.xaml

<TextBlock x:Name="txtDateNow"></TextBlock>

 

Page.xaml.cs

public partial class Page : UserControl

{

    public Page()

    {

        InitializeComponent();

 

        this.Loaded += new RoutedEventHandler(Page_Loaded);

    }

 

    void Page_Loaded(object sender, RoutedEventArgs e)

    {

        //WCF 서비스 객체 생성

        WCFService.ServiceClient service = new WCFBinding.WCFService.ServiceClient();

        //GetDateNow 메서드 결과를 리턴받는 이벤트

        service.GetDateNowCompleted += new EventHandler<WCFBinding.WCFService.GetDateNowCompletedEventArgs>(service_GetDateNowCompleted);

        //비동기 호출

        service.GetDateNowAsync();

    }      

 

    //서비스로부터 호출결과를 반환받을 경우

    void service_GetDateNowCompleted(object sender, WCFBinding.WCFService.GetDateNowCompletedEventArgs e)

    {

        txtDateNow.Text = e.Result.ToShortDateString();

    }

}

Result

-       Microsoft Silverlight

http://silverlight.net/

-       실버라이트 정보 공유 카페

http://cafe.naver.com/mssilverlight.cafe

-       ScottGu's Blog

http://weblogs.asp.net/scottgu/pages/silverlight-posts.aspx

-       MSDN Library (Silverlight)

http://msdn.microsoft.com/ko-kr/library/cc838158(VS.95).aspx

ü  Silverlight 배포하는 방법

1.     Object 태그를 이용한 방법

-       Naver에서 보면 퍼가기와 같은 기능 구현이 가능하며, 특정 웹 서버의 제약 없이 구동 할 수 있어 Silverlight 배포 추천 방법이라 할 수 있습니다.

2.     Silverlight.js의 함수를 이용한 방법

3.     ASP.NET Silverlight 컨트롤을 이용한 방법

-       3번과 배포 방법은 웹사이트가 닷넷 환경이어야 한다는 제약이 있습니다.

ü  Object 태그를 이용한 방법 (알아두면 좋은 것)

1.     Object 태그의 필수적인 속성

속성

내용

Id

HTML 안에 포함될 실버라이트 플러그인의 이름

Data

실버라이트를 어떻게 로드할지에 대한 MIME 타입

Type

실버라이트의 버전

Height

실버라이트를 나타낼 높이(픽셀, %, 둘 다 지정가능)

Width

실버라이트를 나타낼 넓이(픽셀, %, 둘 다 지정가능)

2.     속성과 이벤트의 주요 파라미터

파라미터

내용

Source

URI형식으로 나타낸 실버라이트 파일의 주소이고, 기본 값은 null입니다.

onError

실버라이트에서 에러가 발생할 경우 그 에러 내용을 Javascript로 전달하여 보여줍니다.

onResize

실버라이트의 ActalHeight, ActualWidth 속성이 변경될 때 발생하는 이벤트이며, 처음 로드할 때도 발생하지만 Full-Screen 모드로 변경될 때는 발생하지 않습니다.

3.     선택적인 파라미터

파라미터

내용

background

실버라이트가 로드될 때의 배경색으로 기본값은 null입니다.

enableHtmlAccess

HTML DOM에서 실버라이트 개체로의 접근이나 실버라이트에서 HTML 컨텐트로의 접근을 허용할지에 대한 여부로 기본값은 false입니다.

initParams

실버라이트 런타임으로 전달할 초기 설정 문자열로 콤마(,)을 이용해서 여러 개의 문자열을 구분하여 전달 할 수 있습니다.(key1=value1,key2=value2,key3=value3)

maxFrmaerate

1초간 보여줄 프레임 수의 최대치로 기본값은 60입니다. 이 값은 높을수록 사용자 브라우저의 성능을 늦출 수 있고, 또한 낮을수록 애니메이션이 상당히 부자연스러울 수 있습니다.

splashScreenSource

Source 파라미터에서 지정한 파일이 다운로드 되는 동안의 로딩을 보여줄지에 대한 여부입니다.

windowless

HTML과 혼합되어 사용할 수 있는 Windowless 모드를 설정할 지에 대한 여부로 기본 값은 fasle입니다. 이 속성은 MS 원도우에서 동작되는 브라우저에만 작동됩니다.

*음영 처리된 부분은 기억해 두시는 겟 좋습니다.

4.     추가적인 이벤트 파라미터

파라미터

내용

onLoad

실버라이트가 에러없이 로드되고 모든 내용이 표시될 때 발생하는 이벤트입니다.

onSourceDownloadComplete

Source 파라미터에서 지정한 파일의 다운로드가 완료될 때 발생하는 이벤트입니다.

onSourceDownloadProgressChanged

Source 파라미터에서 지정한 파일의 다운로드가 진행될 떄 발생하는 이벤트입니다.

5.     애니메이션의 진단을 위한 추가 파라미터

-       설정한 속성 외에도 프레임 속도를 브라우저에 보여주거나 렌더링되는 위치를 진단해 보고 싶을 경우 사용합니다. 이 부분에 대해서는 자세히 정리 하지 않겠지만 도움이 될 만한 사이트 주소를 걸어두도록 하겠습니다. (링크)

 

 

ü  Sample Code

1.     initParams을 이용한 데이터 전달하기

-       Silverlight 응용 프로그램 빌드 시, 생성되는 TestPage.html object태그에 파라미터 추가합니다.

Code

TestPage.html

<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">

             <param name="source" value="DemoSample4.xap"/>

             <param name="onerror" value="onSilverlightError" />

             <param name="background" value="white" />

             <param name="minRuntimeVersion" value="2.0.31005.0" />

             <param name="autoUpgrade" value="true" />

             <param name="initParams" value="message1=demo1,message2=demo2" />

             <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

                           <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Microsoft Silverlight 가져오기" style="border-style: none"/>

             </a>

</object>

-       App.xaml.cs에서 Application_Startup 이벤트에서 해당 값을 가져와서 Page.xaml에서 값 전달 받아, 메시지창 띄우기

Code

App.xaml.cs

private void Application_Startup(object sender, StartupEventArgs e)

{

    string strMessage = e.InitParams["message1"] + e.InitParams["message2"];

    this.RootVisual = new Page(strMessage);

}

Page.xaml.cs

public Page(string strMessage)

{

    InitializeComponent();

 

    MessageBox.Show(strMessage);

}

2.     Silverlight에서 HTML 개체에 접근하기

-       Silverlight 역시 DOM 방식을 이용하여 HTML 엘리먼트에 접근할 수 있습니다.

-       TestPage.html Silverlight div 영역 상단에 우선 HTML 개체인 input 엘리먼트를 추가합니다.

Code

TestPage.html

<input type="text" id="txtDemo" value="demo" />

<div id="silverlightControlHost">

             <object data="data:application/x-silverlight," type="application/x-silverlight-2" width="100%" height="100%">

                           <param name="source" value="DemoSample4.xap"/>

                           <param name="onerror" value="onSilverlightError" />

                           <param name="background" value="white" />

                           <param name="minRuntimeVersion" value="2.0.31005.0" />

                           <param name="autoUpgrade" value="true" />

                           <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

                                        <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Microsoft Silverlight 가져오기" style="border-style: none"/>

                           </a>

             </object>

             <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

</div>

-       Page.xaml에서 텍스트 박스와 버튼 컨트롤 추가하고, 버튼 클릭 이벤트에 텍스트 박스의 값을 HTML개체인 input value에 넣은 로직을 구현해보겠습니다.

Code

Page.xaml

<UserControl x:Class="DemoSample4.Page"

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

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

    Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="White" Orientation="Horizontal">

        <TextBox x:Name="TextBox1"  Width="150" Height="20"></TextBox>

        <Button x:Name="Button1" Width="100" Height="20" Content="클릭" Click="Button1_Click"></Button>

    </StackPanel>

</UserControl>

Page.xaml.cs

//추가 네임스페이스

using System.Windows.Browser;

 

private void Button1_Click(object sender, RoutedEventArgs e)

{

    //현재 HTML 페이지의 Document 가져오기

    HtmlDocument document = HtmlPage.Document;

 

    //GetElementById input 개체 접근

    HtmlElement element = document.GetElementById("txtDemo");

 

    //GetAttribute value 값 가져오기

    //element.GetAttribute("value");

 

    //SetAttribute value 값 설정하기

    element.SetAttribute("value", TextBox1.Text);

}

Result

  =>

ð  상단 영역은 HTML 개체이고, 아래는 Silverlight 영역입니다.

ð  Silverlight 영역의 텍스트박스에 텍스트 입력 후, 클릭 하시면, HTML 개체의 값이 변경되는 것을 볼 수 있습니다.

3.     HTML 엘리먼트의 이벤트 구독하기

-       테스트 페이지에 2번과 같이 Silverlight 영역 상단에 텍스트박스와 버튼 개체를 추가합니다.

Code

TestPage.html

<input type="text" id="txtDemo" value="demo" />

<input type="button" id="btnDemo" value="메시지 보이기" />

-       Page.xaml.cs에서 Page() 생성자에 HTML 개체 이벤트를 로직을 추가합니다.

Code

Page.xaml.cs

public Page()

{

    InitializeComponent();

 

    //이벤트 구독

    HtmlElement btnElement = HtmlPage.Document.GetElementById("btnDemo");

    btnElement.AttachEvent("onclick", new EventHandler<HtmlEventArgs>(this.OnBtnDemoClicked));

}

 

private void OnBtnDemoClicked(object sender, EventArgs e)

{

    HtmlElement txtElement = HtmlPage.Document.GetElementById("txtDemo");

    MessageBox.Show(txtElement.GetAttribute("value"));

}

Result

4.     Silverlight Javascript의 연동

-       Silverlight에서 Scriptable 어트리뷰트를 제공해 주며, 어트리뷰트를 선언함으로써 자바스크립트로의 접근을 허용할 수 있습니다.

-       Silverlight 응용 프로젝트 생성 후, TestPage.html 파일에 input 엘리먼트를 추가하고, Silverlight Object 태그에 id가 지정되어 있지 않는다면, id를 지정합니다.

Code

<body>

    메시지 입력 : <input type="text" id="txtMessage" /><br />

    <input type="button" id="btnReg" onclick="RegMessage()" value="등록" />

 

    <div id="silverlightControlHost">

                           <object id="silverlightObject" data="data:application/x-silverlight-2,"  type="application/x-silverlight-2" width="100%" height="100%">

                                        <param name="source" value="ClientBin/DemoSample4.xap"/>

                                        <param name="onerror" value="onSilverlightError" />

                                        <param name="background" value="white" />

                                        <param name="minRuntimeVersion" value="2.0.31005.0" />

                                        <param name="autoUpgrade" value="true" />

                                        <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;">

                                       <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Microsoft Silverlight 가져오기" style="border-style: none"/>

                                        </a>

                           </object>

                           <iframe style='visibility:hidden;height:0;width:0;border:0px'></iframe>

    </div>

</body>

-       Page.xaml에서 받은 텍스트를 보여줄 TextBlock를 선언하고, Page.xaml.cs에서 HTML의 자바스크립트에서 접근할 수 있는 속성과 메서드를 만들겠습니다.

Code

Page.xaml

<UserControl x:Class="DemoSample4.Page"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White">

        <TextBlock x:Name="txtMessage" Text="메시지 : " ></TextBlock>

    </Grid>

</UserControl>

 

Page.xaml.cs

[ScriptableType]

public partial class Page : UserControl

{

    public string message;

 

    public Page()

    {

        InitializeComponent();

        HtmlPage.RegisterScriptableObject("MessageInfo", this);

    }

 

    [ScriptableMember()]

    public void AlertMessage()

    {

        txtMessage.Text = "메시지 : " + this.Message;

 

        //자바스크립트 함수 호출하기

        //MessageBox.Show("등록되었습니다."); 와 동일함.

        HtmlElement alertScript = HtmlPage.Document.CreateElement("script");

        alertScript.SetAttribute("text", "alert('등록되었습니다.');");

        HtmlPage.Document.DocumentElement.AppendChild(alertScript);

    }

  

    [ScriptableMember()]

    public string Message

    {

        get { return message; }

        set { message = value; }

    }

}

Description

ð  클래스 속성에 [ScriptableType]를 선언하면, HtmlPage.RegisterScriptableOjbect() 메소드를 통해 모든 공용 속성, 메서드 및 이벤트를 JavaScript 코드에서 사용할 수 있으며, Javascript에서의 접근을 위해 반드시 선언하여야 합니다.

ð  각각의 속성에 선언한 [ScriptableMember()] 어트리뷰트는 HTML스크립트에서 해당 코드에 접근할 수 있도록 허용하기 위해 선언해 주어야 합니다.

-       TestPage.html 에서 RegMessage() 스크립트를 작성합니다.

Code

<script type="text/javascript">

    function RegMessage() {

 

        //실버라이트 객체

        var host = document.getElementById("silverlightObject");

 

        //사용자 정보 등록

        host.content.MessageInfo.Message = document.getElementById("txtMessage").value;

 

        //사용자 메서드 호출

        host.content.MessageInfo.AlertMessage();

    }

</script>

ð  HtmlPage.RegisterScriptableOjbect()에서 선언하였던 Script Key를 통해 JavaScript 코드에서 접근이 가능합니다.

Result

=>

ü  Understand ControlTemplate

1.     템플릿을 활용하면 컨트롤의 전체 모양을 바꿀 수 있을 뿐만 아니라, 컨트롤의 컨텐트 영역만도 바꿀 수 있으며, 컨트롤이 가지고 있는 애니메이션 역시도 바꿀 수 있습니다

2.     대부분의 컨트롤들은 컨트롤 클래스를 상속하고 있는데, 템플릿은 이 컨트롤 클래스의 Template 속성을 사용하게 됩니다. 리소스 형태 또는 컨트롤에 속성 엘리먼트로 Template 속성 값을 설정하게 됩니다.

3.     템플릿 속성 지정 방법

-       컨트롤 속성 엘리먼트로 지정하는 방법

Code

<Grid x:Name="LayoutRoot" Background="White">

    <Button x:Name="Button1" Width="100" Height="50" Content="버튼1" >

        <Button.Template>

            <ControlTemplate>

                <Grid>

                    <!-- 중략 -->

                </Grid>

            </ControlTemplate>

        </Button.Template>

    </Button>

</Grid>

ð  가장 쉽고 명백하지만, 다른 컨트롤과 공유되지 않기 때문에 매우 제한된 경우에 주로 사용합니다.

-       컨트롤 템플릿 리소스로 값 설정하는 방법

Code

<Grid x:Name="LayoutRoot" Background="White">

    <Grid.Resources>

        <ControlTemplate x:Key="buttonTemplate">

            <Grid>

                <!-- 중략 -->

            </Grid>

        </ControlTemplate>

    </Grid.Resources>

    <Button x:Name="Button1" Width="100" Height="50" Content="버튼1" Template="{StaticResource buttonTemplate}" ></Button>

</Grid>

ð  템플릿을 리소스에서 정의하며, x:Key 속성을 설정하여 각 컨트롤들이 바인딩을 통해 값을 설정하게 됩니다.

-       스타일 리소스로 값 설정하는 방법(스타일의 Setter를 통해 템플릿 속성값을 변경)

Code

<Grid x:Name="LayoutRoot" Background="White">

    <Grid.Resources>

        <Style x:Key="buttonStyle" TargetType="Button">

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="Button">

                        <Grid>

                            <!-- 중략 -->

                        </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

    </Grid.Resources>

    <Button x:Name="Button1" Width="100" Height="50" Content="버튼1" Style="{StaticResource buttonStyle}" ></Button>

</Grid>

ð  가장 많이 쓰이는 방식으로, Setter를 통해 설정된 속성값에 템플릿을 정의하는데 바인딩 표현식을 사용할 수 있어, 유연하게 활용할 수 있습니다.

 

ü  Sample Code

1.     버튼 컨트롤 모양 바꾸기

-       템플릿에 그라디언트가 적용된 타원 버튼을 만들어보겠습니다.

Code

<UserControl x:Class="DemoSample4.Page"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White">

        <Grid.Resources>

            <Style x:Key="buttonStyle" TargetType="Button">

                <Setter Property="Template">

                    <Setter.Value>

                        <ControlTemplate>

                            <Grid>

                                <Ellipse>

                                    <Ellipse.Fill>

                                        <LinearGradientBrush EndPoint="0.5, 1" StartPoint="0.5, 0">

                                            <GradientStop Color="#FF000000" Offset="1" />

                                            <GradientStop Color="#FFFFFFFF" Offset="0" />

                                        </LinearGradientBrush>

                                    </Ellipse.Fill>

                                </Ellipse>

                            </Grid>

                        </ControlTemplate>

                    </Setter.Value>

                </Setter>

            </Style>

        </Grid.Resources>

       

        <Button Width="100" Height="50" Content="버튼1" Style="{StaticResource buttonStyle}"></Button>

    </Grid>

</UserControl>

 

Result


Description

ð  버튼 컨트롤 모양을 바꾸는데는 성공하였지만, “버튼1”이라는 컨트롤의 텍스트 즉, 컨텐트 내용이 표시되지 않았습니다.

-       ContentPresenter을 통한 컨트롤의 컨텐트 영역을 표시합니다.

Code

<!-- 생략 -->

<Grid.Resources>

    <Style x:Key="buttonStyle" TargetType="Button">

        <Setter Property="Template">

            <Setter.Value>

                <ControlTemplate>

                    <Grid>

                        <Ellipse>

                            <Ellipse.Fill>

                                <LinearGradientBrush EndPoint="0.5, 1" StartPoint="0.5, 0">

                                    <GradientStop Color="#FF000000" Offset="1" />

                                    <GradientStop Color="#FFFFFFFF" Offset="0" />

                                </LinearGradientBrush>

                            </Ellipse.Fill>

                        </Ellipse>

                        <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"/>

                    </Grid>

                </ControlTemplate>

            </Setter.Value>

        </Setter>

    </Style>

</Grid.Resources> <!-- 생략 -->

Result

Description

ð  ContentPresenter의 컨텐트 속성을 이 템플릿이 설정된 컨트롤의 컨텐트 속성과 바인딩을 통해서 동일한 값을 설정할 수 있도록 선언하고 있습니다. (TemplateBinding 사용)

 

ü  Sample Code

1.     ListBox 컨트롤의 SelectionChanged 이벤트를 이용한 DetailView Dialog를 구현

-       DetailView를 위해 DetailView명으로 UserControl(Silverlight 사용자 정의 컨트롤)을 추가합니다.

-       UI 화면 만들고, 닫기 버튼 이벤트를 작성합니다.

Code

DetailView.xaml

<UserControl x:Class="DemoSample3.DetailView"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White">

        <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="OrangeRed"></Rectangle>           

       

        <Button x:Name="btnClose" Content="닫기" Width="100" Height="50" Click="btnClose_Click"></Button>

    </Grid>

</UserControl>

 

DetailView.xaml.cs

// 닫기 버튼 이벤트를 추가

private void btnClose_Click(object sender, RoutedEventArgs e)

{

    Visibility = Visibility.Collapsed;

}

-       초기 페이지 Page.xaml ListBox 컨트롤 Item 선택 이벤트를 작성합니다.

Code

Page.xaml

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="DemoSample3.Page"

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

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

    xmlns:detailview="clr-namespace:DemoSample3"

    >

    <Grid x:Name="LayoutRoot" Background="DarkOrange" >

        <!-- 중략 -->

        ………

        <ListBox x:Name="lbResult" Grid.Row="1"  SelectionChanged="lbResult_SelectionChanged">

            <ListBox.ItemTemplate>

                <DataTemplate>

                    <!-- 중략 -->

………

                </DataTemplate>

            </ListBox.ItemTemplate>

        </ListBox>

       

        <!-- Modal Detail View UserControl 추가 -->

        <detailview:DetailView x:Name="DetailView" Grid.Row="1" Visibility="Collapsed"></detailview:DetailView>

    </Grid>

</UserControl>

Page.xaml.cs

private void lbResult_SelectionChanged(object sender, SelectionChangedEventArgs e)

{

    DetailView.Visibility = Visibility.Visible;

}

Description

ð  Silverlight 초기 페이지 Page.xaml 상단에 DetailView UserControl을 추가하기 위해 태그를 추가합니다. (ASP.NET 에서 UserControl 추가하는 것과 유사합니다.)

ð  DetailView 컨트롤 추가 한 후, Visiblity 속성을 Collapsed를 지정하여, 기본적으로 화면에 보이지 않게 하고, ListBox 컨트롤의 Item 선택 이벤트에 DetailView 컨트롤 Visible 처리 합니다.

Result
     

     

2.     DataContext 를 이용하여 DetailView 상세 화면 구현하기

-       DetailView에 상세 데이터를 표현하기 위해 UI를 변경하였습니다.

(데이터 표현하기 위한 TextBlock 추가)

Code

DetailView.xaml

<UserControl x:Class="DemoSample3.DetailView"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White">

        <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Fill="OrangeRed"></Rectangle>

 

        <StackPanel Orientation="Vertical">

            <StackPanel  Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">책 이름 :</TextBlock>

                <TextBlock x:Name="txtBookName"  Margin="5" Text="{Binding BookName}"></TextBlock>

            </StackPanel>

            <StackPanel Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">책 소개 :</TextBlock>

                <TextBlock x:Name="txtBookDesc" Margin="5" Text="{Binding Description}"></TextBlock>

            </StackPanel>

            <StackPanel Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">작성자 :</TextBlock>

                <TextBlock x:Name="txtBookAuthor" Margin="5" Text="{Binding Author}"></TextBlock>

            </StackPanel>

            <StackPanel Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">책 가격 :</TextBlock>

                <TextBlock x:Name="txtBookPrice" Margin="5" Text="{Binding Price}"></TextBlock>

            </StackPanel>

            <StackPanel Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">발행사 :</TextBlock>

                <TextBlock x:Name="txtBookPublisher" Margin="5" Text="{Binding Publisher}"></TextBlock>

            </StackPanel>

            <StackPanel Margin="7" Orientation="Horizontal">

                <TextBlock Margin="5">발행일 :</TextBlock>

                <TextBlock x:Name="txtBookPubDate" Margin="5" Text="{Binding PubDate}"></TextBlock>

            </StackPanel>

            <Button x:Name="btnClose" Content="닫기" Width="100" Height="50" Click="btnClose_Click"></Button>

        </StackPanel>

       

    </Grid>

</UserControl>

-       ListBox 컨트롤의 Item 선택시 DetailView 컨트롤에 DataContext를 이용하여 데이터 전송

Code

Page.xaml

private void lbResult_SelectionChanged(object sender, SelectionChangedEventArgs e)

{

    Book book = (Book)lbResult.SelectedItem;

 

    DetailView.DataContext = book;

    DetailView.Visibility = Visibility.Visible;

}

Result


Description

ð  DetailView UserControl과 같이 FrameworkElement가 데이터 바인딩에 참여하는 경우, 해당 DataContext를 가져오거나 설정할 수 있으며, DataContext는 특정 컨텍스트가 다른 컨텍스트에 바인딩될 수 있는 시나리오의 작업을 원활하게 수행할 수 있도록 바인딩 가능한 속성입니다.

 

u  Understand DataBinding

1.    데이터 바인딩의 개념

-      우선, UI 엘레먼트와 데이터 개체와의 연결을 만드는 과정이라고 보시면 됩니다.

-      바인딩 원본 개체의 특정 속성이 바인딩대상 엘리먼트의 의존 속성과 다르거나 원본 개체 속성의 값이 가공해야 할 경우 변환기(ValueConverter)를 통해 변경해야 합니다.

-      데이터 바인딩 기본 개념도

    데이터 바인딩의 장점  

-      모든 개체들의 속성(Property)이 바인딩을 지원합니다.

-      데이터 템플릿과 스타일을 통해 데이터표현이 자유롭고 유연합니다.

-      UI로 부터 비즈니스 로직을 완벽히 분리할 수 있습니다.

2.    데이터 흐름

-      BindingMode열거형

속성

설명

OneWay

바인딩이 만들어지거나 바인딩 원본 개체 속성이 변경되었을 때 바인딩 대상 개체의 속성 값을 변경합니다.

OneTime

바인딩이 만들어질 때만 바인딩 대상 개체의 속성 값을 변경합니다.

TwoWay

바인딩 원본과 대상 개체의 속성 중 하나가 변경되면 나머지 하나의 속성 값을 변경합니다.

-      OneWay, TwoWay와 같이 바인딩 원본 개체의 속성값이 변경되었을 때 대상 개체의 속성값을 변경하기 위해서는 INotifyPropertyChanged 인터페이스를 구현해야만 합니다.

3.    데이터 바인딩 표현식

<object Property=”{Binding}” …/>

<object Property=”{Binding propertyPath}” …/>

<object Property=”{Binding oneOrMoreBindingProperties}” …/>

<object Property=”{Binding propertyPath , oneOrMoreBindingProperties }” …/>

 

u  Sample Code

1.    마우스 왼쪽 버튼 클릭 이벤트로 TextBlock 색깔 바꾸기

-      텍스트 블록에 Foreground 데이터 바인딩하기

Code

Page.xaml

<UserControl x:Class="DemoSample2.Page"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White" >

        <TextBlock x:Name="TextBlock1" Margin="10" Foreground="{Binding ChangingColor}">DataBinding Sample Code</TextBlock>

    </Grid>

</UserControl>

 

Page.xaml.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Documents;

using System.Windows.Input;

using System.Windows.Media;

using System.Windows.Media.Animation;

using System.Windows.Shapes;

 

namespace DemoSample2

{

    public partial class Page : UserControl

    {

 MyColors myColor = new MyColors();

 

        public Page()

        {

            InitializeComponent();

 

            myColor.ChangingColor = new SolidColorBrush(Colors.Red);

            this.TextBlock1.DataContext = myColor;

        }

    }

 

    public class MyColors

    {

        private SolidColorBrush changingColor;

 

        public SolidColorBrush ChangingColor

        {

            get { return changingColor; }

            set { changingColor = value; }

        }

    }

}

Description

ð  Page.xaml 텍스트 블록의 Foreground 속성에 바인딩합니다.

ð  데이터 바인딩을 위한 원본 개체를 만들기 위해 MyColors 클래스를선언하였습니다.

ð  Page()에서 Object 개체에 데이터 바인딩을 지정하였습니다.

Result

 

-      마우스 왼쪽 버튼 클릭 이벤트 추가

Code

Page.xaml

<TextBlock x:Name="TextBlock1" Margin="10" Foreground="{Binding ChangingColor}" MouseLeftButtonDown="TextBlock1_MouseLeftButtonDown">DataBinding Sample Code</TextBlock>

 

Page.xaml.cs

private void TextBlock1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

    myColor.ChangingColor = new SolidColorBrush(Colors.Black);

}

Description

ð  마우스 왼쪽 버튼 클릭 이벤트를 추가하였습니다. 빌드 후, 결과 화면을 보시면, 상단 이미지와 동일하게 텍스트 블록 색깔 변화가없는 것을 볼 수 있습니다.

ð  속성 값 변경을 감지해서 대상 속성의 값을 변경하기 위해서는INotifyPropertyChanged 인터페이스를 반드시 구현해 주어야 합니다.

-      INotifyPropertyChanged인터페이스 구현

Code

public class MyColors : INotifyPropertyChanged

{

    public event PropertyChangedEventHandler PropertyChanged;

 

    private SolidColorBrush changingColor;

    public SolidColorBrush ChangingColor

    {

        get { return changingColor; }

        set

        {

            changingColor = value;

            NotifyPropertyChaged("ChangingColor");

        }

    }

 

    private void NotifyPropertyChaged(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

}

2.    ListBox컨트롤에 DataBinding 하기

-      Part3.“Naver OpenAPI 를 이용한 Book검색코드에서 DataGrid 컨트롤를 삭제하고, ListBox 컨트롤로 변경한 후, 데이터 보여주기

Code

Page.xaml

// DataGrid 컨트롤 삭제하고, ListBox 컨트롤 로 대체함.

<ListBox x:Name="lbResult" Grid.Row="1"></ListBox>

 

Page.xaml.cs

void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

{

    if (e.Error == null)

    {

        //Using LINQ to XML to Parse NaverOpenAPI XML Items into Book Class

        XDocument xmlBooks = XDocument.Parse(e.Result);

 

        var books = from book in xmlBooks.Descendants("item")

                    select new Book

                    {

                        BookName = (string)book.Element("title"),

                        LinkUrl = new Uri((string)book.Element("link")),

                        ImageUrl = new Uri((string)book.Element("image")),

                        Author = (string)book.Element("author"),

                        Price = (int)book.Element("price"),

                        Publisher = (string)book.Element("publisher"),

                        PubDate = (string)book.Element("pubdate"),

                        ISBN = (string)book.Element("isbn"),

                        Description = (string)book.Element("description")

                    };

 

        // XML Parse 한 데이터 바인딩하기

        lbResult.ItemsSource = books;

    }

}

Result

Description

ð  검색 버튼 클릭 시, ListBox 에 해당 데이터 영역에바인딩된 컬렉션명이 나타나는데, ListBox 컨트롤 부분에 <ListBox x:Name="lbResult" DisplayMemberPath="BookName" Grid.Row="1"></ListBox> 어떤 데이터를보여줄지 매핑을 하지 않았기 때문입니다. 위와 같이 DisplayMemberPath를 지정해 주시면,아래와 같이 원하는 데이터를 화면에 보여줍니다.


-      ListBox.ItemTemplate를 이용한 DataTemplate 구현하기

Code

Page.xaml

<ListBox x:Name="lbResult" Grid.Row="1">

    <ListBox.ItemTemplate>

        <DataTemplate>

            <StackPanel Orientation="Vertical">

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 이름 : </TextBlock>

                    <TextBlock x:Name="txtBookName"  Margin="5" Text="{Binding BookName}"></TextBlock>

                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 소개 :</TextBlock>

                    <TextBlock x:Name="txtBookDesc" Margin="5" Text="{Binding Description}"></TextBlock>

                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 발행일 :</TextBlock>

                    <TextBlock x:Name="txtBookPubDate" Margin="5" Text="{Binding PubDate}"></TextBlock>

                </StackPanel>

            </StackPanel>

        </DataTemplate>

    </ListBox.ItemTemplate>

</ListBox>

Result


Description

ð  ListBox 1개 이상의 정보를 보여줄 경우, ListBox 컨트롤의 ItemTemplate안에 DateTemplate를 정의하여 표현하고자하는 UI를 표현할 수 있습니다.

ð  DataTemplate 안에는 한 개의 컨트롤만 사용 가능하나, 여러 개의 컨트롤을 사용할 경우, StackPanel를 감싸줘서 사용할 수 있습니다.

3.     Tooltips (중요)

-      Part3“Silverlight Network 이해하기 에서 Silverlight Application보안을 위한 URL 접근이 제약되어 있고, 보안 정책 파일을 통해 특정 클라이언트의 접근을허용할 수 있다고 설명 드렸습니다. 우선 샘플 코드를 통해 자세한 설명을 이어가겠습니다.

-      ListBox컨트롤의 ItemTempalte 에검색한 책 이미지를 넣어보겠습니다.

Code

Page.xaml

<ListBox x:Name="lbResult" Grid.Row="1" >

    <ListBox.ItemTemplate>

        <DataTemplate>

            <StackPanel Orientation="Vertical">

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 이미지 :</TextBlock>

                    <Image Source="{Binding ImageUrl}" Width="16" Height="10"></Image>

                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 이름 :</TextBlock>

                    <TextBlock x:Name="txtBookName"  Margin="5" Text="{Binding BookName}"></TextBlock>

                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 소개 :</TextBlock>

                    <TextBlock x:Name="txtBookDesc" Margin="5" Text="{Binding Description}"></TextBlock>

                </StackPanel>

                <StackPanel Orientation="Horizontal">

                    <TextBlock Margin="5">책 발행일 :</TextBlock>

                    <TextBlock x:Name="txtBookPubDate" Margin="5" Text="{Binding PubDate}"></TextBlock>

                </StackPanel>

            </StackPanel>

        </DataTemplate>

    </ListBox.ItemTemplate>

</ListBox>

Result


Description

ð  결과 화면처럼 에러 코드 : 4001 , 범주 : ImageError , 메시지 : AG_E_NETWORK_ERROR 가 발생하는 것을 볼 수 있습니다. 좀 더 자세히 알아보기 위해 HttpWatch, Fildder IE 개발 툴을 사용하여 요청한기록(아래 이미지)을 보면 요청한 도메인 최상위 루트에 clientaccesspolicy.xml 파일과 crossdomain.xml를먼저 요청하는 것을 볼 수 있습니다. 크로스 도메인 접근시 자동으로 요청하는 2개의 파일입니다.

ð  Clientaccesspolicy.xml 파일은 Silverlight에서 사용하는 보안 정책 파일이고, Crossdomain.xml 파일은 기존에 어드비 플래시에서 사용하는 정책 파일로, 어떤 파일과 어떤 디렉토리를 접근 허용할지를 설정해 놓은 규약서라고 보시면 됩니다.

-      보안 정책 파일 작성하고 배포하기

ð  이 사이트의 모든 경로나 파일의 접근이 가능하도록 작성하였습니다.

Code

Clientaccesspolicy.xml

<?xml version="1.0" encoding="utf-8"?>

<access-policy>

  <cross-domain-access>

    <policy>

      <allow-from http-request-headers="*">

        <domain uri="*"/>

      </allow-from>

      <grant-to>

        <resource path="/" include-subpaths="true"/>

      </grant-to>

    </policy>

  </cross-domain-access>

</access-policy>

추가 설명 (예시)

<resource path="/demo" include-subpaths="false"/> 로 지정시,

허용되는 접근

demo#intro

/demo?bar=true#intro

허용되지 않는 접근

/demo

/demo.txt

/demo/sample

/demo/sample.txt

/demo/sample?bar=true

/sample

 

<resource path="/demo" include-subpaths="true"/> 로 지정시,

허용되는 접근

/demo/sample

/demo/sample.txt

/demo/sample?bar=true

/demo#intro

허용되지 않는 접근

/sample

Crossdomain.xml

<?xml version="1.0"?>

 

<!DOCTYPE cross-domain-policy SYSTEM

"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">

 

<cross-domain-policy>

  <allow-access-from domain="*"/>

  <allow-http-request-headers-from domain="* " headers="*" />

</cross-domain-policy>

ð  위 코드와 같이 작성한 후, 사이트 최상위 루트에 배포하시면 됩니다.

 

u  Understand Style

1.     Setter를 통해 속성의 값을 설정할 수 있으며, 이렇게 설정된 속성값들은 하나의 스타일로 묶이게 되며, 여러 컨트롤에 적용이 가능합니다. HTML페이지에 정의한 스타일시트(.CSS) 개념과 유사하다고 보시면 됩니다.

-       스타일 선언은 리소스에 해야 하며, 리소스는 Silverlight특정 레이아웃 컨트롤 또는 페이지 단위로 그 적용 범위를 제어 할 수 있습니다.

-       선언된 스타일 리소스가 여러 개의 페이지에 공통으로 적용될 경우는 Application의 리소스를 사용하시면 됩니다.

u  Sample Code

1.     스타일 정의 하지 않고 일반적인 UI (컨트롤에 스타일 정의)

Code

<UserControl x:Class="DemoSample1.Page"

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

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

    Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="White">

<Button x:Name="Button1" Width="100" Height="50" Margin="10" Content="버튼1" Background=" Red "></Button>

        <Button x:Name="Button2" Width="100" Height="50" Margin="10" Content="버튼2" Background=" Red "></Button>

    </StackPanel>

</UserControl>

2.     스타일 정의 후, 적용한 UI (레이아웃의 리소스에 스타일 정의)

Code

<UserControl x:Class="DemoSample1.Page"

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

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

    Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="White">

        <StackPanel.Resources>

            <Style TargetType="Button" x:Key="buttonStyle">

                <Setter Property="Width" Value="100"></Setter>

                <Setter Property="Height" Value="50"></Setter>

                <Setter Property="Margin" Value="10"></Setter>

                <Setter Property="Background" Value="Red"></Setter>

            </Style>

        </StackPanel.Resources>

       

        <Button x:Name="Button1" Style="{StaticResource buttonStyle}" Content="버튼1"></Button>

        <Button x:Name="Button2" Style="{StaticResource buttonStyle}" Content="버튼2"></Button>

    </StackPanel>

</UserControl>

ð  1번과 2번의 결과 화면은 동일하며, 아래 이미지와 같습니다.

Result

3.     Setter.Value 속성 엘리먼트 사용

-       1번과 2번의 경우는, 컨트롤의 너비나 색과 같이 어트리뷰트 형태로 속성값을 지정하였지만, 그라디언트와 같이 복잡한 형태의 속성값을 지정하기 위해서는 Setter Value 속성 엘리먼트를 통해 지정할 수 있습니다.

Code

<UserControl x:Class="DemoSample1.Page"

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

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

    Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="White">

        <StackPanel.Resources>

            <Style TargetType="Button" x:Key="buttonStyle">

                <Setter Property="Width" Value="100"></Setter>

                <Setter Property="Height" Value="50"></Setter>

                <Setter Property="Margin" Value="10"></Setter>

                <Setter Property="Background">

                    <Setter.Value>

                        <LinearGradientBrush EndPoint="0.5, 1" StartPoint="0.5, 0">

                            <GradientStop Color="White" Offset="0"></GradientStop>

                            <GradientStop Color="Black" Offset="1"></GradientStop>

                        </LinearGradientBrush>

                    </Setter.Value>

                </Setter>

            </Style>

        </StackPanel.Resources>

       

        <Button x:Name="Button1" Style="{StaticResource buttonStyle}" Content="버튼1"></Button>

        <Button x:Name="Button2" Style="{StaticResource buttonStyle}" Content="버튼2"></Button>

    </StackPanel>

</UserControl>

Result
               

4.     코드 비하인드에서 스타일 정의

Code

public partial class Page : UserControl

{

    public Page()

    {

        InitializeComponent();

 

        Style style = new Style(typeof(Button));

        style.Setters.Add(new Setter(ForegroundProperty, new SolidColorBrush(Colors.Red)));

        style.Setters.Add(new Setter(WidthProperty, 100));

        style.Setters.Add(new Setter(HeightProperty, 50));

        style.Setters.Add(new Setter(MarginProperty, 10));

 

        this.Button1.Style = style;

    }

}

 

u  Understand Silverlight Networking

1.     다양한 네트워크 통신을 지원합니다.

-       HTTP 통신 뿐만 아니라 TCP 통신을 위한 Socket 또한 지원합니다.

-       웹 서비스나 WCF 서비스로 데이터를 교환 할 수 있으며, RSS와 같은 Feed를 쉽게 가져올 수도 있습니다.

2.     네트워크 통신을 위한 클래스

-       WebClient (System.Net) 클래스

ð  일반 XML과 같은 데이터를 가져오기 위해 사용합니다.

-       SyndicationFeed (System.ServiceModel.Syndication) 클래스

ð  RSS ATOM과 같은 Feed 데이터를 해당 클래스를 활용하여 보다 쉽게 Feed 데이터를 가져올 수 있습니다.

ð  TCP 프로토콜의 통신을 지원하는 Socket 클래스를 제공하고, Socket의 경우 양방향으로 데이터를 주고 받을 수 있고, 비동기 이벤트와 메서드들을 제공합니다.

3.     보안을 위한 URL 접근 제약

-       Silverlight는 기본적으로 크로스 도메인의 통신을 지원하지 않습니다.

ð  demosample1.kr에서 제공하는 서비스를 demosample2.kr이라는 곳에서 호출하여 사용할 수 없습니다. 하지만, 보안 정책 파일을 통해서 특정 클라이언트의 접근을 허용할 수 있습니다. 추후에 샘플 코드를 통해 자세히 소개하겠습니다.

클래스명

WebClient HTTP클래스

Image클래스와 MediaElement 클래스(프로그레시브)

XAML 소스 파일

Font 파일

미디어 스트리밍

허용된 스키마

HTTP, HTTPS

HTTP, HTTPS, FILE

HTTP, HTTPS, FILE

HTTP, HTTPS, FILE

HTTP

크로스 스키마 접근

허용되지 않음

허용되지 않음

허용되지 않음

안됨

HTTP에서는 허용되지 않음

크로스 도메인 접근

보안정책 파일에서 필요 HTTPS에서 HTTPS라면 허용되지 않음

HTTPS에서 HTTPS가 아닐 경우 허용

HTTPS에서 HTTPS가 아닐 경우 허용

허용되지 않음

HTTPS에서 HTTPS가 아닐 경우 허용

 

u  Sameple Code

1.     Naver OpenAPI 를 이용한 Book Search (WebClient 클래스 이용)

-       UI 만들기

Code

<UserControl xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  x:Class="DemoSample.Page"

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

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

    >

    <Grid x:Name="LayoutRoot" Background="DarkOrange" >

        <Grid.RowDefinitions>

            <RowDefinition Height="60"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

        </Grid.RowDefinitions>

       

        <Grid Grid.Row="0">

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="*"></ColumnDefinition>

                <ColumnDefinition Width="300"></ColumnDefinition>

                <ColumnDefinition Width="100"></ColumnDefinition>

            </Grid.ColumnDefinitions>

           

            <Border CornerRadius="10" Background="Beige" Margin="10">

                <TextBlock Text="Naver OpenAPI를 이용한 책 검색" Margin="10" FontSize="16"></TextBlock>

            </Border>

            <TextBox x:Name="txtSearhWord" Width="700" Height="40" Grid.Column="1" HorizontalAlignment="Left" FontSize="20"  ></TextBox>

            <Button x:Name="btnSearch" Grid.Column="2" Content="검색" Width="90" Height="50" Click="btnSearch_Click" ></Button>

           

        </Grid>

       

       <data:DataGrid x:Name="dgResult" Grid.Row="1"></data:DataGrid>

    </Grid>

</UserControl>

Result

-       WebClient 클래스를 이용하여 검색 데이터(XML) 가져온 후, DataGrid에 데이터 바인딩 시키기

Code

private void btnSearch_Click(object sender, RoutedEventArgs e)

{

    string strSearchWord = txtSearhWord.Text;

    string strSearchUrl = string.Format("http://openapi.naver.com/search?key=acb8d10036417f370d5db98b94f3be49&target=book&query={0}&display=5&start=1&sort=sim", strSearchWord);

 

    WebClient webClient = new WebClient();

    webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);

    webClient.DownloadStringAsync(new Uri(strSearchUrl));

}

 

void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

{

    if (e.Error == null)

    {

        // 검색 XML 데이터 바인딩하기

        dgResult.ItemsSource = e.Result;

    }

}

Result

Description

ð  검색 클릭 시, XML 구조가 한 열에 그려지는 것을 확인 할 수 있습니다. 데이터 그리드에 알맞게 나타내 주기 위해, LINQ를 이용하여 보여주고자 UI에 맞게 XML 데이터를 Parse 하겠습니다.

-       LINQ를 사용하여 검색 XML 데이터 Parse하여 데이터 바인딩 하기

Code

1.     Book 클래스

ð  XML 데이터를 맵핑하기 위해 “Book” 클래스를 정의한 후, 데이터에 알맞은 타입으로 프로퍼티를 생성해보겠습니다.

public class Book

{

    public string BookName { get; set; }

    public Uri LinkUrl { get; set; }

    public Uri ImageUrl { get; set; }

    public string Author { get; set; }

    public int Price { get; set; }

    public string Publisher { get; set; }

    public string PubDate { get; set; }

    public string ISBN { get; set; }

    public string Description { get; set; }

}

2.     Page.xaml 클래스

void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

{

    if (e.Error == null)

    {

        //Using LINQ to XML to Parse NaverOpenAPI XML Items into Book Class

        XDocument xmlBooks = XDocument.Parse(e.Result);

 

        var books = from book in xmlBooks.Descendants("item")

                    select new Book

                    {

                        BookName = (string)book.Element("title"),

                        LinkUrl = new Uri((string)book.Element("link")),

                        ImageUrl = new Uri((string)book.Element("image")),

                        Author = (string)book.Element("author"),

                        Price = (int)book.Element("price"),

                        Publisher = (string)book.Element("publisher"),

                        PubDate = (string)book.Element("pubdate"),

                        ISBN = (string)book.Element("isbn"),

                        Description = (string)book.Element("description")

                    };

 

        // XML Parse 한 데이터 바인딩하기

dgResult.ItemsSource = books;

    }

}

Result



 

u  Understand Layouts Controls

1.     Canvas

-       컨트롤 내부에 자식 컨트롤들을 가질 수 있으며, 자식 컨트롤들은 부모 컨트롤의 왼쪽 상단의 시작점을 기준으로 자신의 위치를 고정합니다.

-       Canvas 컨트롤 역시도 또 다른 Canvas 컨트롤을 자식으로 가질 수 있습니다.

Code

<UserControl x:Class="DemoSample.Page"

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

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

    Width="400" Height="300">

    <Canvas x:Name="LayoutRoot" Background="DarkOrange">

<Button Content="Button1" Width="100" Height="50"  Canvas.Top="80" Canvas.Left="50" Canvas.ZIndex="1"  ></Button>

<Button Content="Button2" Width="100" Height="50"  Canvas.Top="120" Canvas.Left="110"  Canvas.ZIndex="0" ></Button>

    </Canvas>

</UserControl>

Result


Description

ð  Canvas.Top는 해당 Canvas 영역의 상단 시작점 좌표를 나타내며, Canvas.Left는 해당 Canvas 영역의 왼쪽 시작점 좌표를 나타냅니다.

ð  Canvas.ZIndex는 해당 Canvas 영역의 렌더링 순서를 나타내며, 숫자가 높을수록, 영역의 상단에 나타납니다.

2.     StackPanel

-       Canvas와 같이, 자식 컨트롤을 가질 수 있습니다. 하지만, 절대 위치를 지정하지 않고, StackPanel에 속한 자식들을 순서대로 표시합니다.

Code

<UserControl x:Class="DemoSample.Page"

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

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

    Width="400" Height="300">

    <StackPanel x:Name="LayoutRoot" Background="DarkOrange" Orientation="Horizontal">

        <Button Width="100" Height="50" Content="Button1"></Button>

        <Button Width="100" Height="50" Content="Button2"></Button>

        <Button Width="100" Height="50" Content="Button3"></Button>

    </StackPanel>

</UserControl>

Result

Description

ð  Orientation 속성에 Horizontal(수평), Vertical(수직) 지정으로 자식 컨트롤의 정렬 방향 지정을 합니다.

3.     Grid

-       Grid 컨트롤 역시 자식 컨트롤을 가질 수 있으며, HTML의 테이블과 흡사하지만, 해당 셀에 직접 컨트롤을 위치하지 못합니다.

-       RowDefinitions ColumnDefinitions 속성을 이용하여 그리드의 열과 행을 정의해야 합니다.

Code

<UserControl x:Class="DemoSample.Page"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="DarkOrange" ShowGridLines="True">

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="100"></ColumnDefinition>

            <ColumnDefinition Width="200"></ColumnDefinition>

            <ColumnDefinition Width="*"></ColumnDefinition>

        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>

            <RowDefinition Height="100"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

            <RowDefinition Height="100"></RowDefinition>

        </Grid.RowDefinitions>

        <Button Width="100" Height="50" Content="Button1" Grid.Row="0"></Button>

        <Button Width="100" Height="50" Content="Button2"  Grid.Row="2" Grid.Column="2"></Button>

        <Button Width="100" Height="50" Content="Button3"  Grid.Row="1" Grid.Column="1" Grid.RowSpan="2"></Button>

    </Grid>

</UserControl>

Result


Description

ð  코드의 음영 부분을 보시면 3 3열로 정의해 보았습니다. 이때, 행과 열의 Width Height 를 지정해 주셔야 합니다. 유심히 보시면, 정의 부분의 Width, Height * 로 지정한 부분이 있는데, 열과 행 크기를 비율로 설정할 수 있습니다.

ð  아래 코드로 설명하자면, 3열로 각각 *, *, 2* Height를 지정하였습니다.

이 같은 경우는 그리드 영역를 비율로 설정합니다. 따라서 아래 코드는 Grid 높이가 300이므로, 첫번째 열 높이 100, 두번째 열 높이 200, 세번째 열 높이 100으로 자동 지정됩니다.

<Grid x:Name="LayoutRoot" Background="DarkOrange" ShowGridLines="True" Height="300">

        <Grid.RowDefinitions>

            <RowDefinition Height="*"></RowDefinition>

            <RowDefinition Height="*"></RowDefinition>

            <RowDefinition Height="2*"></RowDefinition>

</Grid.RowDefinitions>

<Button Width="100" Height="50" Content="Button1" Grid.Row="0"></Button>

        <Button Width="100" Height="50" Content="Button2"  Grid.Row="2"></Button>

        <Button Width="100" Height="50" Content="Button3"  Grid.Row="1"></Button>

</Grid>

 

u  Visual Studio 2008을 이용한 Silverlight 기반 솔루션 만들기

1.     파일/새로 만들기에서 프로젝트를 선택합니다.

2.     새 프로젝트 대화 상자에서 개발 언어 선택 후, Silverlight 를 선택합니다. (Microsoft Silverlight Tools for Visual Studio 2008 SP1이 설치되어 있어야 Silverlight 프로젝트 형식이 나타납니다.)

3.     템플릿 항목에서 Silverlight 응용 프로그램을 선택 한 후, 프로젝트 이름 입력 후, 확인합니다. (대상 플렛폼이 .NET Framework 3.5 로 선택되어 있어야 합니다.)

         

4.     Silverlight 응용 프로그램 추가 대화상자에서 Silverlight 응용 프로그램 호스팅 방법을 선택합니다.

-       Silverlight 응용 프로그램과 Silverlight 컨트롤을 호스팅하는 ASP.NET 기반의 웹 사이트를 구분하여 프로젝트를 구성하는 경우 "솔루션에 Silverlight를 호스팅할 새 ASP.NET 웹 프로젝트 추가"를 선택하고, 웹 프로젝트의 타입과 이름을 추가로 입력합니다.

-       솔루션에 Silverlight 기반 응용프로그램 프로젝트만을 구성하는 경우, “빌드할 때 Silverlight를 호스팅할 테스트 페이지를 자동으로 생성항목을 선택합니다.


u  Silverlight 응용 프로그램 이해하기

1.     XAML 파일

-       Silverlight WPF 응용 프로그램의 UI를 지정하기 위하여 이용 될 수 있는 XML 기반의 파일입니다.

2.     App.xaml 파일

-       Sivlerlight 응용 프로그램의 시동과 구동을 위한 메인 클래스입니다. 이 클래스는 패키지 파일(.xap)이 다운로드 되면 Silverlight 플러그-인에 의하여 관리됩니다.

3.     Page.xaml 파일

-       Page 클래스는 응용프로그램에서 메인 UI를 표시하는 역할을 하며, UserControl로 부터 상속을 받고 XAML 마크업 파일과 .cs, .vb의 코드비하인드 파일의 쌍으로 구성되어 있습니다.

4.     Xap 파일

-       Silverlight 응용 프로그램의 패키지 파일로, 표준 .zip compression 압축 산법을 극소화하기 위하여 클라이언트 다운로드 크기를 이용합니다.

5.     Silverlight 응용 프로그램을 호스팅하는 웹사이트의 구성 요소

-       .aspx, .html 로 구성된 두 개의 페이지로 구성되어 있으며, Silverlight 응용 프로그램 프로젝트 이름에 TestPage라는 이름이 붙어 있습니다.

-       .html 페이지는 Silverlight 응용프로그램을 호스팅하기 위해 <object> 태그를 사용합니다.

-       .aspx 페이지는 .html 과 유사한 결과물을 얻기 위해 ASP.NET Silverlight 서버 컨트롤을 사용합니다.

               


u  Sample Code

1.     기본 컨트롤(버튼) 추가

-       버튼 컨트롤을 아래와 같은 코드를 추가합니다.

Code

<UserControl x:Class="DemoSample.Page"

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

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

    Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="DarkOrange">

        <Button x:Name="MyButton" Content="버튼" Width="100" Height="50"></Button>

    </Grid>

</UserControl>

Description

Button 컨트롤을 보시면 x:Name라는 Attribute 값에 MyButton이라고 지정하였고, Content버튼이라는 텍스트를 넣었습니다.

ð  x:Name를 설명드리자면 코드 숨김 또는 일반 코드에서 인스턴스화된 개체에 액세스하기 위해 개체 요소를 고유하게 식별할 때 쓰입니다. (ASP.NET으로 보시면 개체 ID로 보시면 됩니다.)

ð  Content ASP.NET 버튼컨트롤의 Text 라고 보시면 됩니다. (컨트롤의 속성은 ASP.NET 컨트롤과 비슷하므로 금방 이해할 수 있습니다.)

Result

2.     이벤트 핸들러 추가

-       Click 이벤트를 추가해 보겠습니다. Click=” 입력시, 아래 이미지와 같이 나타납니다.

엔터 키 또는 Tab 키를 누르면, Click 이벤트 핸들러 함수명을 x:Name에 해당 이벤트명이 붙어 자동 지정되며, Code Behide 클래스에도 이벤트 핸들러 함수가 자동으로 추가됩니다. (ASP.NET 과 유사함)

-       버튼 클릭시, 버튼 컨트롤 Text“Hello World” 로 변경하는 이벤트 추가해 보겠습니다.


3.     ToolTips

-       xaml 파일에서 Code Behide 클래스로 가는 단축키 : F7

-       Code Behide 클래스에서 xaml 파일로 가는 단축키 : Shift + F7


1. .NET Framework를 이용한 Silverlight 개발하기 / Silverlight 개발 시작하기


2. Silverlight 입력 이벤트에 대한 핸들러 작성


3. 기본 제공 컨트롤의 모양 바꾸기


4. 커스텀 컨트롤 만들기


5. Silverlight 애플리케이션이 로드 되는 동안 Splash 스크린 보여주기


6. 데이터 컬렉션으로 작업하기


7. Silverlight에서 Plain XML 메시지 보내고 받기


8. WCF 서비스를 만들고 Proxy를 통해 접근하기


9. Silverlight 로 신디케이션 피드에 접근하기


+ Recent posts