이 기사에서 다루는 내용:
|
이 기사에서 사용하는 기술: .NET Framework 3.0 |
<FlowDocument xmlns=’http://schemas.microsoft.com/winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’> <Paragraph>The quick <Bold>brown fox</Bold> jumps over the lazy dog. </Paragraph> </FlowDocument>
다른 XAML UI에서보다 이 유동 문서에서 HTML과의 유사성이 더욱 확연히 드러남을 알 수 있습니다. 실제 요소 이름은 다르지만 적어도 단순한 문서에서의 기본 방식은 매우 유사합니다. 일반적으로 유동 문서는 많은 수의 블록으로 이루어진 FlowDocument 루트 요소로 시작됩니다. 블록은 흐름을 구성하는 요소로, 다른 블록 형식도 있지만 대개 위의 예와 같이 텍스트 단락으로 이루어집니다. 이러한 단락에는 위의 예에 있는 굵은 글꼴의 두 단어와 같은 다른 요소가 포함될 수 있습니다. 다른 XAML 문서와 마찬가지로 XAML 문서로 인식되기 위해서는 루트 요소에 XAML 고유의 네임스페이스 정의가 필요합니다. 이는 XAML에만 해당하는 세부 구현 규칙으로 유동 문서와는 관련이 없습니다. 네임스페이스 정의는 독립된 유동 문서에만 필요합니다. 유동 문서는 상위 XAML UI의 일부일 수도 있으며, 이 경우 UI의 루트 요소에 네임스페이스 정의가 포함됩니다.물론 브라우저에서 볼 수 있는 HTML 소스와는 달리, 다른 UI 요소에서와 마찬가지로 유동 문서의 XAML도 사용자에게 표시되지 않습니다. 대신 사용자에게는 최종 렌더링된 문서만 표시됩니다. 단, 이 경우에는 다양한 방법으로 결과를 표시할 수 있습니다. 가장 간단하게는 Windows SDK와 함께 제공되는 유틸리티인 XamlPad에 입력하는 방법이 있습니다(그림 1 참조).그림 1 XamlPad에 표시된 간단한 유동 문서 (더 크게 보려면 이미지를 클릭하십시오.)물론 문서의 정의와 포함된 레이아웃은 이 예보다 훨씬 복잡할 수 있습니다. 유동 문서에서는 기울임꼴, 밑줄, 글꼴 색, 서체 등 필요한 모든 서식이 지원됩니다. 그림 2에는 위의 예보다 조금 더 복잡한 예가 나와 있습니다. 그리고 그림 3에는 이 유동 문서의 결과가 나와 있습니다.Figure 2 추가 서식 및 글머리 기호 목록<FlowDocument xmlns=’http://schemas.microsoft.com/winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’> <Paragraph FontFamily=”Calibri” FontWeight=”Bold” FontSize=”24”> WPF Flow Documents</Paragraph> <Paragraph>WPF Flow Documents are <Italic>quite sophisticated</Italic>. They support all common layout options, as well as many you probably do <Span Foreground=”Red”>not expect</Span>.</Paragraph> <List> <ListItem><Paragraph>First List Item</Paragraph></ListItem> <ListItem><Paragraph>Second List Item</Paragraph></ListItem> <ListItem><Paragraph>Third List Item</Paragraph></ListItem> </List> <Paragraph>Of course, Flow Documents also support the definition of <Bold><Span FontFamily=”Comic Sans MS” FontSize=”24” Foreground=”Blue”>in line</Span></Bold> font sizes and font faces. </Paragraph> </FlowDocument>그림 3 조금 더 복잡한 서식의 유동 문서 (더 크게 보려면 이미지를 클릭하십시오.)이 예는 인라인 서식이 적용된 몇 개의 단락을 표시합니다. 또한 몇 개의 목록 항목이 들어 있는 List라는 또 다른 형식의 블록을 보여 줍니다. List에 포함된 각 목록 항목에는 다른 블록이 포함되어 있습니다. 때문에 목록 항목에 단순히 텍스트를 넣는 대신 각 항목마다 단락 요소를 추가했습니다. 그리고 원한다면 각 항목에 여러 단락을 추가하거나 다른 블록 형식을 추가할 수도 있습니다. 이렇게 하면 목록의 단일 항목 내에 복잡한 레이아웃을 만들 수 있습니다. 각 항목 요소마다 간단한 텍스트 문자열만 표시할 수 있는 HTML에서는 이러한 복잡한 레이아웃 구현이 문제가 되는 경우가 많습니다.유동 문서의 기본 개념기본적인 유동 문서를 몇 가지 살펴보았으므로 기본적인 개념을 다시 한번 짚어보도록 하겠습니다. 앞서 설명한 바와 같이 유동 문서는 블록의 컬렉션으로 구성됩니다. 내부적으로 모든 블록은 System.Windows.Documents.Block 클래스에서 파생되는 WPF 클래스입니다. 그리고 Block은 체인의 몇 단계 위에 있는 ContentElement에서 파생됩니다. ContentElement는 WPF에서 상당히 낮은 수준에 있는 클래스로 문서 정의에 최적화되어 있습니다. 이러한 방식은 UIElement에서 파생되는 WPF 인터페이스를 정의하는 데 사용되는 컨트롤과 다소 유사합니다. 두 가지 상속 트리는 개념적으로는 유사하지만 완전히 동일하다고는 할 수 없습니다. 다시 말해 WPF 컨트롤과 블록은 서로 직접 결합할 수 없습니다. 예를 들어 단추의 캡션을 텍스트의 단락으로 설정하거나 단추를 단락에 직접 추가할 수는 없습니다. 콘텐츠 컨트롤의 레이아웃과 블록의 레이아웃이 상이하게 작동하기 때문에 컨트롤과 블록 사이에는 미묘한 차이가 있습니다. 다행히 이 두 가지 WPF 요소 형식 간에 해결해야 할 차이는 크지 않습니다. 예를 들어 단추에 서식이 지정된 텍스트로 이루어진 TextBlock 개체를 추가할 수 있으며, 특수한 BlockUIContainer 블록 클래스를 사용하면 블록에 WPF 컨트롤을 추가할 수 있습니다. 결과적으로 유동 문서에 대화형 사용자 인터페이스 요소, 미디어 요소, 3D 요소 등 모든 종류의 WPF 요소를 포함할 수 있으며, 다른 각도에서 보면 컨트롤 콘텐츠의 고급 레이아웃 요소 또는 실제 문서(예: POS 응용 프로그램의 항목 설명)로 유동 문서를 WPF 사용자 인터페이스에 추가할 수 있습니다.개발자가 고유한 블록 클래스를 파생하여 직접 문서 렌더링 엔진을 향상시킬 수 있으므로 이론적으로 사용 가능한 블록에는 제한이 없습니다. 따라서 필자가 알고 있는 어떠한 다른 문서 렌더링 엔진에서도 제공되지 않는 자율성을 얻을 수 있습니다. 그러나 일반 문서 작성자에게 노출되는 블록의 수는 대개 제한됩니다. 그림 4에는 가장 중요한 블록 형식의 목록이 나와 있습니다.Figure 4 중요 블록 형식
블록 설명 Paragraph 텍스트(다양한 서식이 지정될 수 있음)가 들어 있습니다. List 다양한 종류(번호 매기기, 글머리 기호 등)의 목록이 들어 있습니다. Table Microsoft Word 또는 HTML의 표와 유사한 표가 들어 있습니다. BlockUIContainer 전체 문서 흐름의 일부를 구성하는 다양한 UI 요소가 들어 있습니다. Section 다른 블록의 그룹이 들어 있습니다. Section은 여러 단락에 같은 글꼴 특성을 적용하는 경우와 같이 블록 그룹에 공통 특성을 적용할 때 유용합니다. XAML에서 WPF 유동 문서를 작성할 때에는 특정 형식만 인스턴스화하게 됩니다. 다음 XAML 코드 조각을 한번 살펴보십시오. 앞으로 예를 단순화하기 위해 네임스페이스 정의는 생략하겠습니다.<FlowDocument> <Paragraph>Hello World!</Paragraph> </FlowDocument>이 코드는 FlowDocument 클래스와 Paragraph 클래스(해당 텍스트가 "Hello World!"로 설정됨)를 인스턴스화합니다. 해당 단락은 FlowDocument의 블록 컬렉션에 추가됩니다. 다른 모든 XAML과 마찬가지로 요소 이름은 대/소문자가 구분되고 WPF의 일부로 사용 가능한 클래스에 정확히 매핑됩니다. 또한 동일한 문서를 다음과 같이 프로그래밍 방식으로 작성할 수도 있습니다.FlowDocument doc = new FlowDocument(); Paragraph para = new Paragraph(); para.Inlines.Add(“Hello World!”); doc.Blocks.Add(para);물론 이러한 프로그래밍 방식은 XAML이 제공하는 선언적 방식보다 이해하기가 훨씬 어렵기 때문에 특수한 경우에만 사용됩니다. 필자의 경우 대부분의 보고 엔진에서 생성되는 단순한 표 형태의 출력이 아니라 실제 사용되는 문서와 같이 다양한 서식이 적용된 보고서를 만들어야 할 때 종종 이러한 방법을 사용합니다.단락 자체에 서식이 다양하게 적용된 콘텐츠가 포함되는 경우도 많습니다. 이 경우도 다음과 같이 클래스를 인스턴스화하는 방식으로 구현할 수 있습니다.<Paragraph>Hello <Bold>World!</Bold></Paragraph>이 예의 단락에는 "Hello"(기본 서식 사용)와 "World!"(굵은 글꼴 사용)라는 두 개의 텍스트 세그먼트가 포함되어 있습니다. 이는 이 XAML 코드가 단순히 단락을 인스턴스화하고 텍스트를 문자열로 설정하는 데 그치는 것이 아니라, 각각 서로 다른 서식이 적용된 텍스트를 포함한 두 개의 하위 세그먼트로 이루어진 단락을 만든다는 것을 보여 줍니다. WPF에서는 이러한 세그먼트를 인라인이라고 합니다. 유동 문서에 다양한 형식의 블록을 여러 개 포함될 수 있는 것과 마찬가지로 단락에도 다양한 형식의 인라인이 포함될 수 있습니다. 인라인은 여러 가지로 변형됩니다. 특정 서식 옵션이 적용된 텍스트 세그먼트를 나타내는 인라인을 Span이라고 합니다. 이 예에 사용된 Bold 요소는 기본 글꼴 두께가 굵게 설정된 특수한 형태의 Span입니다. 다른 인라인 유형으로는 기본 서식이 적용된 텍스트 세그먼트인 Run이 있습니다. 따라서 위의 XAML은 실질적으로 다음을 간략하게 표현한 것입니다.<Paragraph> <Run>Hello </Run> <Bold>World!</Bold> </Paragraph>물론 XAML에 인라인을 일일이 정의할 필요가 없다면 간편하겠지만 인라인은 코드에서 생략할 수 없으므로 이 예를 프로그래밍 방식으로 만들려면 인라인의 개념을 이해하는 것이 중요합니다. 앞서 소개한 두 가지 XAML 예를 프로그래밍 방식으로 표현하면 다음과 같습니다.Paragraph para = new Paragraph(); para.Inlines.Add(new Run(“Hello “)); Bold b = new Bold(); b.Inlines.Add(“World!”); para.Inlines.Add(b);Bold는 기본 글꼴 두께가 굵게 설정되어 있는 Span의 특수한 버전으로, Bold 형식은 Span의 하위 클래스이며 FontWeight 속성을 다시 정의합니다. 유사한 특수 Span으로 Italic과 Underline이 있습니다. 그러나 이러한 특수 Span이 꼭 필요한 것은 아니기 때문에 다음과 같이 기본 Span을 사용한 후에 해당 속성을 설정해도 됩니다.<Paragraph>Hello <Span FontWeight=”Bold”>World!</Span></Paragraph>물론 텍스트의 특정 부분에 Bold 및 Italic 태그를 사용하여 굵은 글꼴이나 기울임꼴과 같은 특성을 직접 지정하면 간편하고 직관적이므로 <Span FontWeight="Bold">보다 <Bold>를 사용하는 경우가 훨씬 많습니다. 그러나 단순한 굵은 글꼴 외에도 수많은 속성을 설정할 수 있을 뿐만 아니라 그러한 대부분의 서식 옵션이 동일한 형식이기 때문에 <Span> 요소는 매우 유용합니다. 사실 자주 사용하는 서식 옵션 중에는 별도의 Span이 없는 것들이 많습니다. 그 대표적인 예가 바로 글꼴 이름 설정입니다. HTML과는 달리 유동 문서에는 <Font> 요소가 없으며, 글꼴은 다음과 같이 설정됩니다.<Paragraph>Hello <Span FontFamily=”Comic Sans MS” FontSize=”24”> World!</Span></Paragraph>FontFamily를 비롯한 여러 속성은 모든 유동 문서 클래스에 일관되게 사용됩니다. 예를 들어 인라인이 아니라 전체 단락에 글꼴을 적용하려는 경우 다음과 같이 Span을 사용하지 않고 설정할 수 있습니다.<Paragraph FontFamily=”Comic Sans MS” FontSize=”24”>Hello World!</Paragraph>Span과 Run 외에 다른 인라인도 있습니다. 그 중 몇 가지 흥미로운 인라인을 소개하면 다음과 같습니다.Figure Figure는 블록이 포함된 다소 특수한 인라인입니다. 따라서 Figure는 유동 문서에 포함된 작은 유동 문서라고 할 수도 있습니다. Figure는 단락에 이미지를 배치하여 일반 텍스트가 이미지 주위에 흐르도록 하는 등의 고급 레이아웃 기능에 주로 사용됩니다.Floater Floater는 간단한 그림 형식으로, 일부 그림 배치 옵션이 지원되지 않지만 표준 단락 맞춤 옵션에서 제공되지 않는 간단한 맞춤 기능만 필요한 경우에 유용할 수 있습니다.LineBreak LineBreak 요소는 이름에서 알 수 있듯이 단락에 줄 바꿈을 삽입합니다.InlineUIContainer InlineUIContainer는 BlockUIContainer에 해당하는 인라인으로, 단락의 텍스트에 단추를 배치하는 경우와 같이 WPF 컨트롤을 다른 인라인과 결합해야 할 때 사용됩니다.Figure는 유동 문서에 자주 사용됩니다. (LineBreak도 마찬가지로 늘 사용되지만 특별히 설명할 내용은 없습니다.) 다음은 Figure를 사용하여 유동 문서의 일부로 이미지를 표시하는 예입니다.<Paragraph> <Figure Width=”200”> <BlockUIContainer> <Image Source=”Pictures\Humpback Whale.jpg” /> </BlockUIContainer> <Paragraph Foreground=”Blue” FontFamily=”Consolas”> The Whale</Paragraph> </Figure> The quick brown fox jumps over the lazy dog. The quick brown... </Paragraph>WPF 유동 문서에는 Image 블록이 없습니다. 대신 표준 WPF 컨트롤을 사용하여 BlockUIContainer로 이미지가 포함됩니다. 이러한 방법은 유동 문서에 비디오나 대화형 3D 모델과 같은 콘텐츠를 추가하는 데에도 사용됩니다. 그림 5에는 이와 유사하게 렌더링된 문서가 나와 있습니다.그림 5 이미지 및 캡션 주위에 배치된 텍스트 (더 크게 보려면 이미지를 클릭하십시오.)유동 문서 보기지금까지 몇 가지 간단한 유동 문서를 만들고 XamlPad에서 보는 방법을 살펴보았습니다. 이제 실제 사용 시 유동 문서를 보는 방법을 알아볼 차례입니다. 사용자가 문서의 XAML을 XamlPad에 붙여 넣기를 기대할 수는 없으니까요. XAML 유동 문서를 보는 방법 중 하나로, 확장명이 .xaml인 파일로 저장한 다음 Windows 탐색기에서 두 번 클릭하는 것이 있습니다. 그러면 XAML 파일에 연결된 기본 응용 프로그램(대개 Internet Explorer®)이 실행되고 문서가 나타납니다. 그림 6은 이렇게 표시된 결과를 보여 줍니다.그림 6 Internet Explorer에 표시된 XAML 유동 문서 (더 크게 보려면 이미지를 클릭하십시오.)유동 문서를 웹 응용 프로그램의 일부로 표시할 수 있는 것은 Internet Explorer를 비롯한 브라우저에서 XAML 콘텐츠 표시를 지원하기 때문입니다. 다시 말해, XAML 유동 문서를 웹 서버에 업로드한 경우 다른 사용자가 해당 파일을 검색하면 그림 6과 같이 표시됩니다. 단, 사용자의 컴퓨터에 Microsoft® .NET Framework 3.0이 설치되어 있다는 것을 전제로 합니다. 물론 이러한 기능은 동적으로 작동합니다. 즉, XAML 유동 문서를 바로 생성하여 출력으로 반환하는 ASP.NET 웹 응용 프로그램 또는 기타 서버 쪽 기술을 사용하는 경우, 콘텐츠 형식이 "application/xaml+xml"로 올바르게 설정되어 있으면 유동 문서가 웹 응용 프로그램의 일부로 사용자에게 표시됩니다. 이러한 기능은 여러 시나리오에서 유용하게 사용됩니다. 그림 7은 유동 문서를 생성하는 간단한 ASP.NET 페이지를 보여 줍니다.유동 문서 표시브라우저 또는 XamlPad에서 유동 문서를 표시할 때마다 문서 자체만 표시되는 것이 아니라 다른 항목도 몇 가지 표시됩니다. 구체적으로 말하면 문서의 아래쪽에 몇 가지 컨트롤이 함께 렌더링됩니다. 그림 8에서 보듯이 유동 문서는 기본적으로 FlowDocumentReader 컨트롤을 사용하여 렌더링됩니다. 이 컨트롤은 확대/축소, 페이지 번호 표시, 다양한 보기 모드, 찾기 기능 등의 표준 기능 집합을 제공합니다. 결과적으로 유동 문서는 유동 문서를 표시할 수 있는 일종의 컨트롤을 사용하여 호스팅해야 합니다. 유동 문서의 기본 뷰어는 FlowDocumentReader 컨트롤이며, 다른 컨트롤을 명시적으로 사용하지 않을 경우 이 컨트롤이 자동으로 인스턴스화됩니다. 현재 WPF에서는 유동 문서를 보는 데 사용할 수 있는 세 가지 컨트롤이 제공됩니다.그림 8 FlowDocumentReader 컨트롤의 컨트롤 단추 (더 크게 보려면 이미지를 클릭하십시오.)FlowDocumentScrollViewer 이 컨트롤은 웹 페이지 또는 Microsoft Word의 웹 모양과 유사한 스크롤 막대가 있는 연속된 페이지로 문서를 표시합니다. 그림 9는 스크롤 뷰어에 표시된 문서를 보여 줍니다.그림 9 FlowDocumentScrollViewer 컨트롤 사용 (더 크게 보려면 이미지를 클릭하십시오.)FlowDocumentPageViewer 이 컨트롤은 스크롤 대신 페이지 넘기기 방식을 사용하여 개별 페이지에 유동 문서를 표시합니다. 이는 Word의 전체 화면 읽기와 유사합니다. 그림 10의 페이지 뷰어에는 그림 9의 문서가 FlowDocumentPageViewer 컨트롤을 사용하여 렌더링되어 있으며 스크롤 막대가 페이지 번호 표시 메커니즘으로 대체되었습니다. 단순한 동적 레이아웃이 여러 단으로 이루어진 고급 페이지 표시 레이아웃으로 바뀐 것입니다.그림 10 FlowDocumentPageViewer 컨트롤 사용 (더 크게 보려면 이미지를 클릭하십시오.)FlowDocumentReader 이 컨트롤은 스크롤 뷰어와 페이지 뷰어를 결합한 것으로 사용자가 두 가지 방식 간을 전환할 수 있도록 합니다. 이 컨트롤은 유동 문서에 사용되는 기본 컨트롤로, 복잡한 텍스트를 표시하는 응용 프로그램에 적합합니다. 그림 11에는 그림 9 및 그림 10과 동일한 문서가 스크롤 뷰어 및 페이지 뷰어 방식을 결합한 FlowDocumentReader로 렌더링되어 있습니다. 또한 다른 컨트롤에서는 기본적으로 숨겨져 있는 검색 기능을 제공합니다. 한편 스크롤 뷰어나 페이지 뷰어에서는 찾기가 지원되며 ApplicationCommands.Find 명령을 실행하거나 키보드에서 Ctrl+F를 눌러 찾기를 표시할 수 있습니다. 이 판독기 컨트롤은 페이지 기반 렌더링과 단 및 그림 렌더링 방식이 약간 다른 다중 페이지 보기를 지원합니다.그림 11 FlowDocumentReader 컨트롤 사용 (더 크게 보려면 이미지를 클릭하십시오.)컨트롤은 상황에 따라 선택되지만 FlowDocumentReader는 주로 기본적인 용도로 사용됩니다. 이 컨트롤은 거의 모든 용도로 사용할 수 있고 강력한 기능을 제공할 뿐만 아니라, 많은 경우에 스크롤보다 뛰어난 성능을 발휘하는 페이지 표시 레이아웃도 지원합니다. 이에 대한 자세한 내용은 이 기사의 범위를 벗어나므로 여기서는 다루지 않지만, 스크롤 및 관련 효과(예: 더블링)는 많은 사람들이 디지털 텍스트를 사용하는 이유 중 하나입니다. 페이지 표시 방식은 스크롤 방식보다 자연스럽게 구현되는 경우가 많으며, 디지털 읽기의 사용 범위를 확대하는 데에도 효과적입니다.사용할 컨트롤은 어떻게 정해야 할까요? 간단하지만 다소 원시적인 방법으로, 다음과 같이 원하는 컨트롤을 문서의 XAML에 추가해 볼 수 있습니다.<FlowDocumentScrollViewer xmlns=’http://schemas.microsoft.com/winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’> <FlowDocument> <Paragraph>The quick <Bold>brown fox</Bold> jumps over the lazy dog.</Paragraph> </FlowDocument> </FlowDocumentScrollViewer>이 예에서 문서 루트는 FlowDocumentScrollViewer 태그로 이루어져 있습니다. 따라서 더 이상 순수한 문서만을 정의하는 것이 아니라 스크롤 뷰어를 루트로 사용할 전체 XAML 인터페이스를 정의하는 것입니다. 이 스크롤 뷰어의 콘텐츠는 첫 예에서 소개한 유동 문서입니다. 그러나 여기서는 네임스페이스 정의에 유동 문서 태그가 아니라 스크롤 뷰어 태그가 사용되었습니다. 그림 9에서 그림 11은 이와 같은 방식으로 서로 다른 뷰어 컨트롤을 루트 요소로 사용하여 만들어졌습니다.그런데 이와 같은 방식이 원시적이라고 한 이유는 무엇일까요? 그 이유는 아키텍처의 관점에서 봤을 때 사용자 인터페이스 정의와 실제 데이터를 혼합함으로써 몇 가지 문제가 발생하기 때문입니다. 문서는 인터페이스와 분리하는 것이 훨씬 효과적입니다. 판독기와 문서를 혼합하는 것은 SQL Server™ 테이블을 만들어 Windows Forms DataGrid에서만 표시할 수 있도록 정의하는 것과 같습니다. UI 정의에서 문서를 분리하는 방법은 몇 가지가 있습니다. 위에서 설명한 ASP.NET 방식을 사용하여 유동 문서를 웹 응용 프로그램의 일부로 표시하려면 원하는 뷰어 컨트롤을 사용하여 ASP.NET 페이지를 정의한 후 ASP.NET 코드를 사용하여 데이터베이스 등에 별도로 저장된 실제 콘텐츠와 병합하면 됩니다.반면, 일반적인 WPF 응용 프로그램의 경우 표준 WPF, Windows 및 XBAP(XAML 브라우저 응용 프로그램) 방식으로 사용자 인터페이스를 정의한 다음 문서를 동적으로 로드하면 됩니다. 그림 12에는 필자의 기사(왼쪽 위의 목록 상자에 나열된 기사)가 저장된 가상의 라이브러리를 사용한 간단한 예를 보여 줍니다. 사용자가 목록에서 기사를 선택하면 유동 문서 판독기 컨트롤로 문서가 동적으로 로드되어 폼이 대부분 자동으로 채워집니다. 이 경우 알파 블렌딩과 같은 표준 WPF 기법을 사용할 수 있습니다. 실제 유동 문서는 반투명하여 배경으로 사용된 필자의 사진이 비쳐 보입니다. 또한 응용 프로그램에서 목록 상자, 이미지, 레이블 및 FlowDocumentReader 컨트롤을 사용하여 가상의 기사를 만듭니다.그림 12 Listbox, Image, Label 및 FlowDocumentReader 컨트롤 사용 (더 크게 보려면 이미지를 클릭하십시오.)이 예에서 가장 어려운 부분은 실제 문서를 뷰어 컨트롤로 로드하는 것입니다. 실제 문서를 로드하려면 유동 문서를 비롯한 모든 XAML 콘텐츠를 동적으로 로드할 수 있는 System.Windows.Markup.XamlReader 클래스를 사용해야 합니다. 필자가 listbox의 선택 변경 이벤트에 연결한 코드는 다음과 같습니다.documentReader.Document = (FlowDocument)XamlReader.Load( File.OpenRead(fileName));XAML 파일의 루트 요소는 여러 가지 다른 형식을 나타낼 수 있으므로 Load 메서드는 개체를 반환합니다. 위의 예에서는 반환 값이 FlowDocument라는 것을 이미 알고 있으므로 캐스팅을 수행하고 해당 문서를 FlowDocumentReader 컨트롤의 Document 속성에 할당했습니다. 예에서는 이 컨트롤 인스턴스의 이름을 documentReader로 지정했습니다. 이는 하나의 예일 뿐이라는 점을 잊지 마십시오. 실제 프로덕션 환경에서 사용되는 코드의 경우에는 여기에 오류 처리 코드도 추가해야 합니다.이 예에는 WPF에 대한 모든 사항이 적용됩니다. 예를 들어 판독기 컨트롤은 스타일을 지원하는 표준 WPF 컨트롤일 뿐입니다. 따라서 확대/축소 막대, 보기 모드 스위치, 페이지 표시 컨트롤 등 모든 UI 요소의 모양을 완전히 바꿀 수 있습니다. (단, 검색 상자는 제어할 수 있는 범위가 제한되지만 이 UI를 꼭 사용할 필요는 없습니다.)또한 이 예는 Windows 기반 응용 프로그램이지만 동일한 응용 프로그램을 XBAP로 배포한 후 웹 브라우저에서 실행할 수도 있습니다. 물론, 이때에도 사용자의 컴퓨터에 .NET Framework 3.0이 설치되어 있어야 합니다. Microsoft Silverlight™(이전 코드 이름 "WPF/E")는 WPF 중 일부만 지원하고 유동 문서는 지원하지 않으므로 Silverlight만으로는 부족합니다.유동 문서 작성유동 문서는 어떻게 작성될까요? 물론 개발자가 원한다면 XamlPad와 같은 기초적인 수준의 도구로도 유동 문서를 작성할 수 있지만, 현실적으로 이러한 유동 문서는 별다른 쓸모가 없습니다. 대개 유동 문서는 WYSIWYG 편집기를 사용하거나 기존 문서 형식의 콘텐츠 변환을 통해 만들어집니다. 유동 문서는 XAML에서 정의할 수 있으므로 기존 XML 콘텐츠를 변환하는 방법이 특히 쉽습니다. 그러나 조금만 노력을 기울인다면 HTML 및 Word 문서도 충분히 변환할 수 있습니다. 단, 이러한 용도로 개발된 도구는 아직 없으므로 코딩 작업이 필요합니다.WPF에서는 WYSIWYG 편집에 바로 사용할 수 있는 컨트롤이 제공됩니다. WPF RichTextBox 컨트롤을 사용하면 XAML 유동 문서를 기본적으로 편집할 수 있습니다. 이 컨트롤의 이름만 보면 RTF(서식 있는 텍스트)용이라고 잘못 생각할 수 있습니다. 이 컨트롤이 RTF를 지원하기는 하지만 주로 유동 문서에 사용됩니다. 사실 이 컨트롤은 편집 기능을 지원한다는 점을 제외하면 유동 문서 보기 컨트롤과 동일합니다. RichTextBox 컨트롤을 유동 문서를 표시하는 하나의 방법으로 간주해야 한다는 사람들도 있을 정도입니다.다음 예를 XamlPad에 입력하면 RichTextBox 컨트롤의 작동 방식을 직접 볼 수 있습니다.<RichTextBox xmlns=’http://schemas.microsoft.com/ winfx/2006/xaml/presentation’ xmlns:x=’http://schemas.microsoft.com/winfx/2006/xaml’> <FlowDocument> <Paragraph> The quick brown fox jumps over the lazy dog. </Paragraph> </FlowDocument> </RichTextBox>판독기 컨트롤과 마찬가지로 RichTextBox에도 이 세션에서 유동 문서를 사용하여 자동으로 채울 수 있는 Document 속성이 있습니다. 실제로 텍스트를 편집할 수 있다는 점을 제외하면 이 컨트롤과 FlowDocumentScrollViewer 컨트롤을 통해 구현되는 UI는 매우 유사합니다. 이 텍스트 상자 컨트롤은 항상 유동 문서를 스크롤 방식으로 처리합니다. 페이지 표시 모드 또는 다중 단 모드로는 RichTextBox에서 유동 문서를 편집할 수 없습니다. 그러나 편집 작업의 결과는 다중 단 모드와 페이지 모드를 비롯하여 지금까지 살펴본 어떠한 뷰어 메커니즘으로도 표시할 수 있는 표준 유동 문서로 나타납니다.RichTextBox의 중요한 기능 중 하나는 바로 통합 맞춤법 검사 기능입니다. 이 기능은 다음과 같이 설정할 수 있습니다.<RichTextBox SpellCheck.IsEnabled=”true”> <FlowDocument>...</FlowDocument> </RichTextBox>그림 13은 맞춤법 검사기의 예를 보여 줍니다.그림 13 맞춤법 검사 기능을 실행 중인 RichTextBox 컨트롤 (더 크게 보려면 이미지를 클릭하십시오.)이 컨트롤을 사용할 때 유일하게 문제가 되는 부분은 바로 로드와 저장입니다. 이전 예에서와 같이 RichTextBox의 콘텐츠를 UI XAML로 코딩하는 경우는 거의 없습니다. 대신 문서를 동적으로 로드하고 저장하게 됩니다. RichTextBox에 텍스트를 로드하는 작업은 뷰어 컨트롤의 유동 문서를 로드하는 작업과 동일합니다(위의 내용 참조). 문서 저장 작업은 이와 반대로 이루어집니다. 즉, 다음과 같이 문서 개체를 가져와 다시 XAML로 직렬화해야 합니다.System.Windows.Markup.XamlWriter. Save(richTextBox.Document)이 코드를 실행하면 XAML이 파일 또는 데이터베이스에 저장하거나, 다른 원하는 방식으로 사용할 수 있는 문자열로 반환됩니다.RichTextBox는 매우 유용하지만 신중하게 사용해야 합니다. 유동 문서는 화면에 표시할 문서를 렌더링하는 데 사용되는 가장 정교한 기술이지만 RichTextBox 컨트롤은 그다지 정교하지 않습니다. 다시 말해 작은 문서나 텍스트 조각을 편집하는 데에는 더없이 좋지만 서적, 잡지 또는 마케팅 브로슈어와 같은 복잡한 문서를 작성하는 데에는 적합하지 않습니다. 이렇게 긴 형식의 문서에 사용하기에는 스크롤 레이아웃만 지원하는 렌더링 방식이 너무 단순하고, 따라서 앞으로 짧게 설명할 고급 레이아웃을 시각적으로 표현할 수 없기 때문입니다. 또한 문서 저장 방식도 적합하지 않습니다. XmlWriter 클래스는 메모리 내의 라이브 문서를 사용하여 XAML로 변환할 뿐이며, 스타일과 같은 광범위한 유동 문서 작업의 개념은 지원하지 않습니다. 결과적으로 XAML에서 문서의 모양은 그대로 유지되지만 어지럽고 크기가 너무 큰 경우가 많습니다. 따라서 RichTextBox 컨트롤이 유용한 것은 사실이지만 화면 콘텐츠용 데스크톱 출판 솔루션으로 사용할 수 있으리라고 기대해서는 안 됩니다.레이아웃 기능 살펴보기지금까지 유동 문서를 작성하고 표시하는 방법을 설명했으므로 이제 문서 자체로 돌아가 몇 가지 기능을 살펴보도록 하겠습니다. 유동 문서는 매우 복잡한데다 사용 가능한 모든 기능을 다루면 이 기사의 범위를 훨씬 벗어나게 되므로 중요한 몇 가지만 소개하도록 하겠습니다.필자에게는 최적 단락이라는 기능이 가장 인상적이었습니다. 이 기능을 사용하면 지정한 단락에 공백을 가능한 한 균등하게 배치하여 가독성을 크게 높일 수 있습니다. 최적 단락 기능은 하이픈 넣기와 함께 사용하면 더욱 효과적입니다. 하이픈 넣기는 전체 유동 문서 또는 개별 단락에 즉시 하이픈을 넣는 기본 제공 기능입니다.최적 단락 기능과 하이픈 넣기 기능은 다음과 같이 간단하게 설정할 수 있습니다.<FlowDocument IsOptimalParagraphEnabled=”true” IsHyphenationEnabled=”true”>그림 14는 동일한 문서를 이 두 가지 기능을 사용한 상태와 사용하지 않은 상태로 렌더링한 결과를 보여 줍니다. 두 버전 간의 차이는 미묘하지만 매우 중요합니다. 공백이 균등하게 조정되어 있고 전반적으로 단어 간에 공백이 줄었기 때문에 오른쪽 버전이 훨씬 간결하게 보입니다. 특히 화면에서 많은 양의 텍스트를 읽을 때에는 이 작은 차이가 매우 중요하게 작용할 수 있습니다.그림 14 최적 단락 및 하이픈 넣기 (더 크게 보려면 이미지를 클릭하십시오.)앞서 살펴봤듯이 FlowDocumentReader 컨트롤은 다중 단 방식으로 텍스트를 렌더링합니다. 와이드 스크린 디스플레이의 전체 너비를 모두 채우도록 한 줄로 표시된 텍스트는 읽기가 어렵기 때문에 이 기능도 가독성을 높이는 데 중요한 역할을 합니다. 실제 단의 너비는 콘텐츠 표시에 사용 가능한 전체 너비, 확대/축소 비율, 정의된 단 너비 등의 요인에 따라 다릅니다. 유동 문서의 단 너비는 기본적으로 글꼴 크기의 20배로 설정됩니다. 여기서 글꼴 크기는 장치 독립적 픽셀을 단위로 약 300픽셀(일대일 크기 디스플레이상에서 3 1/8인치)에 해당하는 기본 글꼴 크기를 기준으로 합니다. 이 기본 설정은 다음과 같이 손쉽게 다시 정의할 수 있습니다.<FlowDocument ColumnWidth=”400”>위의 코드를 실행하면 단 너비가 약 400픽셀로 설정됩니다. 그러나 실제 너비가 결정되는 데에는 다른 요인도 작용합니다. 예를 들어 확대/축소율을 50%로 적용하면 실제 단 너비가 200픽셀로 나타납니다. 또한 최소 단 너비가 일반적으로 생각하는 단 너비에 가깝다고 할 수 있습니다. 따라서 사용 가능한 전체 너비가 900픽셀이면 렌더링된 결과에는 900픽셀을 모두 채우기에 충분한 두 개의 단이 포함되어 각 단이 정의된 400픽셀을 초과하게 됩니다. 이러한 동작은 매우 세련된 방식으로 렌더링되는 결과로 이어지므로 대개 문제가 없습니다. 그러나 이러한 동작을 원치 않고 실제로 400픽셀 너비로 단을 표시하려면 다음과 같이 단 너비를 고정할 수 있습니다.<FlowDocument ColumnWidth=”400” IsColumnWidthFlexible=”false”>이제 모든 단이 100% 배율에서 정확히 400픽셀 너비로 나타나고 나머지 공간은 공백으로 남습니다.또 다른 유용한 단 관련 설정으로는 단 간격이 있습니다. 단 간격은 ColumnGap 속성을 통해 조정 가능하며, 역시 장치 독립적인 픽셀 단위를 기준으로 합니다.<FlowDocument ColumnGap=”25”>관련 설정으로 단 사이에 시각적 요소를 정의하는 데 사용되는 단 규칙이 있습니다. 다음 예를 살펴보겠습니다. 이 코드의 결과는 그림 15에 나와 있습니다.그림 15 단 간 규칙이 적용된 유동 문서 (더 크게 보려면 이미지를 클릭하십시오.)<FlowDocument ColumnRuleWidth=”5” ColumnRuleBrush=”Red”>물론 많은 수의 발행물에서 문서의 단 레이아웃이 단순하게 되어 있는 것만은 아닙니다. 하지만 일정한 흐름에서 벗어난 다른 요소가 사용되는 경우도 종종 있습니다. 앞서 살펴본 문서에 이미지를 삽입한 예가 이에 해당합니다. 그림 12는 그래픽 아티스트가 많이 사용하는 정렬 방식을 보여 줍니다. 이 이미지는 두 단 사이에 배치되고 텍스트가 그 주위로 흐릅니다. 그리고 이미지는 어떤 단의 흐름도 방해하지 않으면서 콘텐츠의 정중앙에 위치하고 있습니다. 이러한 레이아웃은 이미 많이 사용되고 있지만 필자가 아는 한 유동 문서를 제외한 동적 화면 읽기 환경에서는 지원되지 않습니다.이러한 레이아웃을 만드는 데 가장 중요한 요소는 문서의 나머지 부분과 동적으로 흐르지 않도록 콘텐츠를 정의할 수 있는 Figure 블록입니다. Figure 태그에 이미지를 넣는 것도 한 가지 방법이지만 그 외에도 다양한 방법으로 응용할 수 있습니다. 예를 들어 다음과 같이 Figure를 사용하여 전체 문서를 가로질러 표시되는 제목을 정의할 수 있습니다.<Paragraph> <Figure HorizontalAnchor=”ContentLeft” VerticalAnchor=”ContentTop” Width=”1Content”> <Paragraph FontSize=”36” FontWeight=”Bold”>Go With The Flow</Paragraph> </Figure> Windows Presentation Foundation in Windows Vista provides a great set of features. </Paragraph>이 코드의 Figure에는 제목 텍스트에 해당하는 다른 단락이 들어 있습니다. 세련되고 유연한 문서를 작성하는 데 사용할 수 있는 몇 가지 유용한 속성이 있습니다. Figure의 너비를 예로 들어 보겠습니다. 너비를 특정 픽셀 수로 설정하는 대신 정확히 콘텐츠의 너비로 설정하여 Figure의 너비가 전체 콘텐츠의 너비로 자동 조정되도록 했습니다.그림 16을 살펴보면 Figure를 통해 배치된 제목이 전체 콘텐츠의 너비에 맞게 조정되도록 설정되어 있고, 그에 따라 4개 단이 모두 아래쪽으로 조정됩니다. 그리고 이미지는 페이지의 가운데에 가로 및 세로로 고정됩니다.그림 16 4개 단에 걸친 제목 (더 크게 보려면 이미지를 클릭하십시오.)콘텐츠에 따라 변화하는 너비가 적용된 Figure라도 항상 콘텐츠의 너비에 맞출 필요는 없습니다. 예를 들어 다음 예의 경우 Figure의 너비가 콘텐츠 너비의 75%가 되도록 설정합니다.<Figure Width=”0.75Content”>또한 단 너비와 같은 다른 항목을 기준으로 너비가 조정되도록 할 수도 있습니다. 다음은 너비가 항상 2개 단의 너비가 되는 Figure의 예입니다. 단, 단이 하나만 표시되면 너비가 1개 단 너비로 축소됩니다.<Figure Width=”2Column”>물론 Figure 높이도 이와 같은 방법으로 정의할 수 있습니다. 하지만 대부분의 경우 Figure는 콘텐츠와 함께 세로로 계속 확장됩니다.다른 중요한 측면으로는 Figure의 위치가 있습니다. 위 코드 조각에서 Figure는 가로로 왼쪽에, 세로로 오른쪽에 고정되도록 설정되어 있습니다. 따라서 실제 정의된 위치에 관계없이 Figure가 현재 콘텐츠 페이지의 왼쪽 위에 나타납니다. 이 예에서는 Figure가 문서의 첫 번째 요소로 정의되어 있기 때문에 어쨌든 관계가 없지만, 해당 제목 앞에 단락이 있었더라도 이러한 설정 때문에 위쪽과 왼쪽으로 이동되었을 겁니다. 그림 12와 그림 16의 사진은 이와 같은 방식으로 가로 앵커를 "PageCenter"로 설정하여 단 사이로 이동되었습니다. 이러한 모든 설정별로 사용 가능한 속성 값은 WPF 설명서를 참조하십시오.아마 수동 코딩 과정이 많이 필요하다는 건 이미 알고 있을 겁니다. 예를 들어 글꼴 이름을 변경해야 할 때마다 블록이나 인라인에 해당 정보를 추가해야 합니다. 지금까지는 간단한 예만 살펴보았으므로 수동 코딩이 큰 문제가 되지는 않았지만, 어떤 서적의 50페이지짜리 챕터에 있는 모든 단락의 글꼴을 변경하는 작업은 수동으로 코딩하기에는 너무 방대합니다. 다행히 WPF의 다른 구성 요소와 마찬가지로 유동 문서에서도 지원되는 스타일이라는 더 나은 방법이 있습니다. 스타일은 실제 유동 문서에 명명 리소스로 정의할 수 있습니다. 다음은 글꼴 정보를 정의하는 스타일입니다.<FlowDocument> <FlowDocument.Resources> <Style x:Key=”MyStyle”> <Setter Property=”TextElement.FontSize” Value=”12” /> <Setter Property=”TextElement.FontFamily” Value=”Bodoni MT” /> </Style> <FlowDocument.Resources> ... </FlowDocument>이렇게 정의한 스타일은 단락과 다른 요소에 다음과 같이 적용할 수 있습니다.<Paragraph Style=”{StaticResource MyStyle}”>The quick... </Paragraph>유동 문서는 그 특성상 스타일이 매우 자주 사용됩니다. 단순한 시나리오를 제외하고는 대부분의 서식 옵션을 개별 인라인의 특성이 아니라 스타일에 정의하는 것이 좋습니다. 스타일을 사용하면 문서를 간결하게 만들 수 있을 뿐 아니라 유지 관리하기도 쉽기 때문입니다.맺음말이 기사가 유동 문서와 그 기능에 대한 기본적인 이해에 그치지 않고 좀 더 유용한 정보를 얻고 여러분의 흥미를 유발하는 계기가 되었으면 합니다. 뷰어 컨트롤의 정교한 스타일, 문서의 하위 클래스 지정 및 확장, 블록, 인라인, 디지털 권한 관리, 텍스트 및 잉크 주석 기능, 고급 글꼴 서식 등 여기서 소개하지 않은 고급 기능에 대해서도 한번 알아보시기 바랍니다.
댓글 영역