WPF에서는 다양한 기능의 UI(사용자 인터페이스) 컨트롤을 사용하여 텍스트 콘텐츠를 프레젠테이션할 수 있습니다. 일반적으로 세 가지 계층으로 텍스트 렌더링을 나눌 수 있습니다.
FormattedText 개체 사용.
상위 수준 컨트롤(예: TextBlock 및 FlowDocument 객체) 사용.
이 항목에서는 텍스트 렌더링 성능 권장 사항을 제공합니다.
문자 모양 수준에서 텍스트 렌더링
WPF(Windows Presentation Foundation)는 텍스트 서식이 완료된 후 가로채고 유지하려는 고객을 위해 글리프에 직접 액세스할 수 있는 문자 모양 수준 태그를 포함한 고급 텍스트 지원을 제공합니다. 이러한 기능을 통해 다음과 같은 각 시나리오의 다양한 텍스트 렌더링 요구 사항을 충족시킬 수 있습니다.
고정된 형식 문서의 화면 표시
인쇄 시나리오
XAML(Extensible Application Markup Language)을 디바이스 프린터 언어로 사용.
Microsoft XPS 문서 작성기입니다.
이전 프린터 드라이버, Win32 애플리케이션에서 고정된 형식으로 출력.
인쇄 대기열 형식
이전 버전의 Windows 및 기타 컴퓨팅 디바이스에 대한 클라이언트를 포함하는 고정된 형식 문서 표시.
비고
Glyphs 및 GlyphRun은 고정 형식 문서 프레젠테이션 및 인쇄 시나리오용으로 디자인되었습니다. WPF는 일반적인 레이아웃 및 UI(사용자 인터페이스) 시나리오에 대해
다음 예제에서는 XAML에서 Glyphs 개체의 속성을 정의하는 방법을 보여 줍니다. 이 예제에서는 로컬 컴퓨터의 C:\WINDOWS\Fonts 폴더에 Arial, Courier New 및 Times New Roman 글꼴이 설치되어 있다고 가정합니다.
<!-- The example shows how to use a Glyphs object. -->
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel Background="PowderBlue">
<Glyphs
FontUri = "C:\WINDOWS\Fonts\TIMES.TTF"
FontRenderingEmSize = "100"
StyleSimulations = "BoldSimulation"
UnicodeString = "Hello World!"
Fill = "Black"
OriginX = "100"
OriginY = "200"
/>
</StackPanel>
</Page>
DrawGlyphRun 사용
사용자 지정 컨트롤이 있고 문자 모양을 렌더링하려는 경우 DrawGlyphRun 메서드를 사용합니다.
WPF는 또한 FormattedText 개체를 사용하여 사용자 지정 텍스트 서식 지정을 위한 하위 수준 서비스를 제공합니다. WPF (Windows Presentation Foundation)에서 텍스트를 렌더링하는 가장 효율적인 방법은 Glyphs 및 GlyphRun을 사용하여 글리프 수준에서 텍스트 콘텐츠를 생성하는 것입니다. 그러나 이러한 효율성에는 대가가 따르는데, 이는 TextBlock, FlowDocument 등 WPF(Windows Presentation Foundation) 컨트롤의 고유 기능인 사용하기 쉬운 서식 있는 텍스트 서식을 잃는 것입니다.
포맷된 텍스트 개체
FormattedText 개체를 사용하면 여러 줄의 텍스트를 그릴 수 있으며, 이 텍스트의 각 문자를 개별적으로 서식 지정할 수 있습니다. 자세한 내용은 서식 있는 텍스트 그리기를 참조하십시오.
서식이 지정된 텍스트를 만들려면 FormattedText 생성자를 호출하여 FormattedText 개체를 만듭니다. 첫 서식 있는 텍스트 문자열을 만든 다음 다양한 서식 지정 스타일을 적용할 수 있습니다. 애플리케이션에서 자체 레이아웃을 구현하려는 경우, FormattedText 객체는 TextBlock와 같은 컨트롤을 사용하는 것보다 더 나은 선택입니다. "FormattedText 개체에 관한 자세한 내용은 서식 있는 텍스트 그리기를 참조하세요."
FormattedText 개체는 하위 수준 텍스트 서식 지정 기능을 제공합니다. 하나 이상의 문자에 여러 서식 지정 스타일을 적용할 수 있습니다. 예를 들어, SetFontSize 및 SetForegroundBrush 메서드를 둘 다 호출하여 텍스트에서 처음 5개 문자의 서식을 변경할 수 있습니다.
다음 코드 예제는 FormattedText 객체를 생성하고 렌더링합니다.
protected override void OnRender(DrawingContext drawingContext)
{
string testString = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor";
// Create the initial formatted text string.
FormattedText formattedText = new FormattedText(
testString,
CultureInfo.GetCultureInfo("en-us"),
FlowDirection.LeftToRight,
new Typeface("Verdana"),
32,
Brushes.Black);
// Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
formattedText.MaxTextWidth = 300;
formattedText.MaxTextHeight = 240;
// Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
// The font size is calculated in terms of points -- not as device-independent pixels.
formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5);
// Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
formattedText.SetFontWeight(FontWeights.Bold, 6, 11);
// Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
formattedText.SetForegroundBrush(
new LinearGradientBrush(
Colors.Orange,
Colors.Teal,
90.0),
6, 11);
// Use an Italic font style beginning at the 28th character and continuing for 28 characters.
formattedText.SetFontStyle(FontStyles.Italic, 28, 28);
// Draw the formatted text string to the DrawingContext of the control.
drawingContext.DrawText(formattedText, new Point(10, 0));
}
Protected Overrides Sub OnRender(ByVal drawingContext As DrawingContext)
Dim testString As String = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor"
' Create the initial formatted text string.
Dim formattedText As New FormattedText(testString, CultureInfo.GetCultureInfo("en-us"), FlowDirection.LeftToRight, New Typeface("Verdana"), 32, Brushes.Black)
' Set a maximum width and height. If the text overflows these values, an ellipsis "..." appears.
formattedText.MaxTextWidth = 300
formattedText.MaxTextHeight = 240
' Use a larger font size beginning at the first (zero-based) character and continuing for 5 characters.
' The font size is calculated in terms of points -- not as device-independent pixels.
formattedText.SetFontSize(36 * (96.0 / 72.0), 0, 5)
' Use a Bold font weight beginning at the 6th character and continuing for 11 characters.
formattedText.SetFontWeight(FontWeights.Bold, 6, 11)
' Use a linear gradient brush beginning at the 6th character and continuing for 11 characters.
formattedText.SetForegroundBrush(New LinearGradientBrush(Colors.Orange, Colors.Teal, 90.0), 6, 11)
' Use an Italic font style beginning at the 28th character and continuing for 28 characters.
formattedText.SetFontStyle(FontStyles.Italic, 28, 28)
' Draw the formatted text string to the DrawingContext of the control.
drawingContext.DrawText(formattedText, New Point(10, 0))
End Sub
FlowDocument, TextBlock 및 레이블 컨트롤
WPF에는 화면에 텍스트를 그리는 데 사용하는 여러 컨트롤이 포함됩니다. 각 컨트롤은 다른 시나리오를 대상으로 하며 고유 기능 및 제한 사항 목록을 가지고 있습니다.
FlowDocument가 TextBlock 또는 Label 이외의 성능에 미치는 영향
일반적으로 TextBlock 요소는 UI(사용자 인터페이스)의 간략한 문장과 같이 제한된 텍스트 지원이 필요할 때 사용해야 합니다. Label는 텍스트 지원이 거의 필요하지 않은 경우 사용할 수 있습니다. FlowDocument 요소는 콘텐츠의 풍부한 프레젠테이션을 지원하는 재배치 가능한 문서용 컨테이너로서, 따라서 TextBlock 또는 Label 컨트롤을 사용하는 것보다 성능에 더 큰 영향을 미칩니다.
Flow 문서에 대한 자세한 내용은 Flow 문서 개요를 참조하세요.
FlowDocument에서 TextBlock 사용 안 함
TextBlock 요소는 UIElement에서 파생됩니다. Run 요소는 TextElement에서 파생되며, UIElement에서 파생된 개체보다 사용이 더 경제적입니다. 텍스트 콘텐츠를 FlowDocument에 표시할 때는 가능한 경우 TextBlock 대신 Run을 사용하세요.
다음 마크업 샘플은 FlowDocument 내에서 텍스트 콘텐츠를 설정하는 두 가지 방법을 보여줍니다.
<FlowDocument>
<!-- Text content within a Run (more efficient). -->
<Paragraph>
<Run>Line one</Run>
</Paragraph>
<!-- Text content within a TextBlock (less efficient). -->
<Paragraph>
<TextBlock>Line two</TextBlock>
</Paragraph>
</FlowDocument>
"텍스트 속성을 설정할 때 실행 사용을 피하기"
일반적으로 Run 내에서 TextBlock을 사용하는 것은 명시적인 Run 개체를 전혀 사용하지 않는 것보다 성능적으로 더 부담이 됩니다. Run을 사용하여 텍스트 속성을 설정하고 있는 경우, 해당 속성을 TextBlock에서 직접 설정하십시오.
다음 태그 샘플에서는 텍스트 속성, 이 경우 FontWeight 속성을 설정하는 두 가지 방법을 보여 줍니다.
<!-- Run is used to set text properties. -->
<TextBlock>
<Run FontWeight="Bold">Hello, world</Run>
</TextBlock>
<!-- TextBlock is used to set text properties, which is more efficient. -->
<TextBlock FontWeight="Bold">
Hello, world
</TextBlock>
다음 표는 명시적 Run 없이 또는 함께 1000개 TextBlock 개체를 표시하는 비용을 보여 줍니다.
| TextBlock 형식 | 만든 시간(ms) | 렌더링 시간(ms) |
|---|---|---|
| 설정 텍스트 속성 실행 | 146 | 540 |
| TextBlock의 텍스트 속성 설정 | 43 | 453 |
Label.Content 속성에 데이터 바인딩 방지
자주 업데이트되는 Label 객체가 String 소스에서 오는 시나리오를 상상해 보세요. Label 요소의 Content 속성을 String 원본 개체에 데이터 바인딩할 때 성능이 저하될 수 있습니다. 원본 String이 업데이트될 때마다 이전 String 객체가 폐기되고 새 String가 재생성됩니다. 왜냐하면 String 객체는 변경 불가능하기 때문에 수정할 수 없습니다. 따라서 이로 인해 Label 개체의 ContentPresenter가 이전 콘텐츠를 버리고 새 콘텐츠를 재생성하여 새로운 String을 표시합니다.
이 문제에 대한 해결책은 간단합니다. Label이 사용자 지정 ContentTemplate 값으로 설정되지 않은 경우 Label을 TextBlock으로 바꾸고 해당 Text 속성을 원본 문자열에 데이터 바인딩합니다.
| 데이터 바인딩된 속성 | 업데이트 시간(ms) |
|---|---|
| 레이블.콘텐츠 | 835 |
| 텍스트블록.텍스트 | 242 |
하이퍼링크
Hyperlink 객체는 흐름 콘텐츠 내에서 하이퍼링크를 호스팅할 수 있는 인라인 수준의 흐름 콘텐츠 요소입니다.
하나의 TextBlock 개체에 대한 하이퍼링크 결합
여러 Hyperlink 요소를 동일한 TextBlock 내에서 함께 그룹화하여 해당 요소 사용을 최적화할 수 있습니다. 이렇게 하면 애플리케이션에서 만드는 개체의 수를 최소화할 수 있습니다. 예를 들어 다음과 같은 여러 개의 하이퍼링크를 표시할 수 있습니다.
MSN 홈 | 내 MSN
다음 마크업 예제에서는 하이퍼링크를 표시하는 데 사용된 여러 TextBlock 요소를 보여 줍니다.
<!-- Hyperlinks in separate TextBlocks. -->
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://www.msn.com">MSN Home</Hyperlink>
</TextBlock>
<TextBlock Text=" | "/>
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>
ko-KR: 다음 마크업 예제에서는 단일 TextBlock을 사용하여 하이퍼링크를 보다 효율적으로 표시하는 방법을 보여줍니다.
<!-- Hyperlinks combined in the same TextBlock. -->
<TextBlock>
<Hyperlink TextDecorations="None" NavigateUri="http://www.msn.com">MSN Home</Hyperlink>
<Run Text=" | " />
<Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>
MouseEnter 이벤트에만 하이퍼링크에 밑줄 표시
TextDecoration 개체는 텍스트에 추가할 수 있는 시각적 장식이지만, 이를 인스턴스화하면 성능에 부담을 줄 수 있습니다. 광범위하게 Hyperlink 요소를 사용하는 경우, MouseEnter 이벤트와 같은 이벤트를 트리거할 때에만 밑줄을 표시하는 것이 좋습니다. 자세한 내용은 하이퍼링크에 밑줄이 그어지는지 여부 지정을 참조하세요.
다음 이미지는 MouseEnter 이벤트가 밑줄이 표시된 하이퍼링크를 트리거하는 방법을 보여 줍니다.
텍스트 장식을 표시하는 하이퍼링크
다음 마크업 샘플은 Hyperlink이 밑줄과 함께 정의된 것과 밑줄 없이 정의된 것을 보여줍니다.
<!-- Hyperlink with default underline. -->
<Hyperlink NavigateUri="http://www.msn.com">
MSN Home
</Hyperlink>
<Run Text=" | " />
<!-- Hyperlink with no underline. -->
<Hyperlink Name="myHyperlink" TextDecorations="None"
MouseEnter="OnMouseEnter"
MouseLeave="OnMouseLeave"
NavigateUri="http://www.msn.com">
My MSN
</Hyperlink>
다음 표에서는 밑줄이 있거나 없는 1000개의 Hyperlink 요소를 표시할 때의 성능 비용을 보여 줍니다.
| 하이퍼링크 | 만든 시간(ms) | 렌더링 시간(ms) |
|---|---|---|
| 밑줄 있음 | 289 | 1130 |
| 밑줄 없음 | 299 | 776 |
텍스트 서식 지정 기능
WPF는 자동 하이픈 넣기와 같은 서식 있는 텍스트 서식 처리 서비스를 제공합니다. 이러한 서비스는 애플리케이션 성능에 영향을 줄 수 있으며 필요한 경우에만 사용해야 합니다.
불필요한 하이픈 넣기 사용 안 함
자동 하이픈 설정은 텍스트 줄의 하이픈 분할 지점을 찾고, TextBlock 및 FlowDocument 개체의 줄에 추가적인 분할 지점을 허용합니다. 기본적으로 이러한 개체에서는 자동 하이픈 넣기 기능이 사용하지 않도록 설정됩니다. 개체의 IsHyphenationEnabled 속성을 true로 설정하여 이 기능을 사용할 수 있습니다. 그러나 이 기능을 사용하면 WPF에서 COM(구성 요소 개체 모델) 상호 운용성이 시작되어 애플리케이션 성능에 영향을 미칠 수 있습니다. 꼭 필요한 경우가 아니면 자동 하이픈 넣기를 사용하지 않는 것이 좋습니다.
신중하게 그림 사용
페이지의 콘텐츠 내에서 절대적으로 위치를 지정할 수 있는 흐름 콘텐츠의 일부를 나타내는 요소입니다. 일부 경우, Figure의 위치가 이미 배치된 콘텐츠와 충돌하면 전체 페이지의 레이아웃이 자동으로 다시 조정될 수 있습니다. 불필요한 레이아웃 다시 조정을 최소화하려면 Figure 요소를 서로 나란히 그룹화하거나 고정된 페이지 크기 시나리오에서 콘텐츠 상단에 선언하세요.
최적 단락
FlowDocument 개체의 최적 단락 기능은 공백이 가능한 한 균등하게 배분되도록 단락을 구성합니다. 기본적으로 최적 단락 기능은 사용하지 않도록 설정됩니다. 개체의 IsOptimalParagraphEnabled 속성을 true로 설정하여 이 기능을 활성화할 수 있습니다. 그러나 이 기능을 사용하면 애플리케이션 성능에 영향을 미칩니다. 꼭 필요한 경우가 아니면 최적 단락 기능을 사용하지 않는 것이 좋습니다.
참고하십시오
- WPF 애플리케이션 성능 최적화
- 애플리케이션 성능 계획
- 하드웨어의 최대 활용
- 레이아웃 및 디자인
- 2D 그래픽 및 영상 처리
- 개체 동작
- 애플리케이션 리소스
- 데이터 바인딩
- 기타 성능 관련 추천 사항
.NET Desktop feedback