Оптимизация производительности: отображение текста

Приложение WPF включает поддержку представления содержимого текста с помощью использования широких функциональных возможностей элементов управления user interface (UI). В целом можно разделить отрисовку текста на три уровня:

  1. Непосредственное использование объектов Glyphs и GlyphRun.

  2. Использование объекта FormattedText.

  3. Использование элементов управления верхнего уровня, таких как объекты TextBlock и FlowDocument.

Этот раздел содержит рекомендации по повышению производительности отрисовки текста.

В этом разделе содержатся следующие подразделы.

  • Отрисовка текста на уровне глифа
  • Объект FormattedText
  • Элементы управления FlowDocument, TextBlock и Label
  • Гиперссылка
  • Возможности форматирования текста
  • Связанные разделы

Отрисовка текста на уровне глифа

Приложение Windows Presentation Foundation (WPF) обеспечивает дополнительную поддержку текста, включая разметку на уровне глифа с прямым доступом к объекту Glyphs для пользователей, которым нужно перехватывать и сохранять текст после форматирования. Эти возможности предоставляют важную поддержку различных требований к отрисовке текста в следующих скриптах.

  • Отображение на экране документов фиксированного формата.

  • Сценарии печати.

    • Extensible Application Markup Language (XAML) как язык принтера.

    • Microsoft XPS Document Writer.

    • Предыдущие драйверы принтера, приведенные из приложений Win32 к фиксированному формату.

    • Формат очереди печати.

  • Представление документов фиксированного формата, включая клиенты предыдущих версий Windows и другие вычислительные устройства.

ПримечаниеПримечание

Объекты Glyphs и GlyphRun предназначены для представления документа фиксированного формата и сценариев печати.Windows Presentation Foundation (WPF) предоставляет несколько элементов для общего макета и сценариев user interface (UI), таких как Label и TextBlock.Дополнительные сведения о макете и скриптах UI см. в разделе Оформление в WPF.

В следующих примерах показано определение свойств объекта Glyphs в Extensible Application Markup Language (XAML). Объект Glyphs представляет вывод объекта GlyphRun в XAML. В примерах предполагается, что на локальном компьютере установлены шрифты Arial, Courier New и Times New Roman в папке C:\WINDOWS\Fonts.

<!-- The example shows how to use a Glyphs object. -->
<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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. Наиболее эффективным способом отрисовки текста в приложении Windows Presentation Foundation (WPF) является создание содержимого текста на уровне глифов с помощью объектов Glyphs и GlyphRun. Однако ценой этой эффективности будет потеря простоты форматирования текста RTF, поддерживаемого встроенными функциональными возможностями элементов управления Windows Presentation Foundation (WPF), таких как FlowDocument и TextBlock.

Объект FormattedText

Объект FormattedText позволяет рисовать многострочный текст, в котором каждый знак можно форматировать отдельно. Дополнительные сведения см. в разделе Рисование форматированного текста.

Чтобы создать форматированный текст, вызовите конструктор FormattedText для создания объекта FormattedText. После создания первоначально отформатированной текстовой строки можно применить весь диапазон стилей форматирования. Если приложению требуется реализовать свой собственный макет, рекомендуется использовать объект FormattedText вместо элемента управления, такого как TextBlock. Дополнительные сведения об объекте FormattedText см. в разделе Рисование форматированного текста.

Объект FormattedText предоставляет возможность низкоуровневого форматирования текста. Можно применить несколько стилей форматирования к одному или нескольким знакам. Например, можно вызвать как метод SetFontSize, так и метод SetForegroundBrush для изменения форматирования первых пяти знаков текста.

В следующем примере кода создается объект FormattedText и выполняется его отображение.

        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
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));
}

Элементы управления FlowDocument, TextBlock и Label

Приложение WPF содержит несколько элементов управления для рисования текста на экране. Каждый элемент управления предназначен для различных скриптов и имеет свой собственный список возможностей и ограничений.

Элемент управления FlowDocument влияет на производительность сильнее, чем элементы управления TextBlock и Label

В целом, элемент TextBlock следует использовать, если требуется ограниченная поддержка текста, например для короткого предложения, которое нужно вставить в user interface (UI). Label может использоваться, если необходима минимальная поддержка текста. Элемент FlowDocument является контейнером для повторно форматируемых документов, поддерживающих представление форматированного содержимого, и поэтому сильнее влияет на производительность, чем использование элементов управления TextBlock или Label.

Дополнительные сведения об объекте FlowDocument см. в разделе Общие сведения о документе нефиксированного формата.

Необходимость избегать использования элемента управления TextBlock в элементе управления FlowDocument

Элемент TextBlock является производным от класса UIElement. Элемент Run является производным от класса TextElement, который является менее затратным в использовании, чем объект, производный от класса UIElement. По возможности используйте Run вместо TextBlock для отображения текстового содержимого в объекте FlowDocument.

В следующем примере разметки показано два способа настройки текстового содержимого в объекте 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 для настройки свойств текста

В общем случае использование 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>

В следующей таблице показана производительность отображения 1000 объектов TextBlock с использованием и без использования явного объекта Run.

Тип элемента TextBlock

Время создания (мс)

Время отображения (мс)

Задание свойств текста с помощью Run

146

540

Задание свойств текста с помощью TextBlock

43

453

Необходимость избегать привязки данных к свойству Label.Content

Представим скрипт, в котором имеется объект Label, часто обновляемый из источника String. Если осуществляется привязка свойства Content элемента Label к исходному объекту String, может наблюдаться низкая производительность. Каждый раз при обновлении источника String устаревший объект String удаляется и создается новый объект String, поскольку объект String является постоянным (он не может быть изменен). Это, в свою очередь, приводит к тому, что объект ContentPresenter объекта Label удаляет устаревшее содержимое и создает новое содержимое для отображения нового объекта String.

Имеется простое решение этой проблемы. Если для объекта Label не установлено пользовательское значение ContentTemplate, то замените объект Label объектом TextBlock и выполните привязку данных его свойства Text к строке источника.

Свойство привязки данных

Время обновления (мс)

Label.Content

835

TextBlock.Text

242

Гиперссылка

Объект Hyperlink является элементом растягиваемого содержимого встроенного уровня, позволяющим размещать гиперссылки в растягиваемом содержимом.

Объединение гиперссылок в одном объекте TextBlock

Можно оптимизировать использование нескольких элементов Hyperlink, группируя их вместе в одном объекте TextBlock. Это позволяет минимизировать число создаваемых в приложении объектов. Например, возможно, потребуется отобразить несколько гиперссылок, как показано ниже:

MSN Home | My MSN

В следующем примере разметки показано несколько элементов TextBlock, используемых для отображения гиперссылок:

<!-- Hyperlinks in separate TextBlocks. -->
<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="https://www.msn.com">MSN Home</Hyperlink>
</TextBlock>

<TextBlock Text=" | "/>

<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>

В следующем примере разметки показан более эффективный способ отображения гиперссылок, на этот раз — с помощью одного элемента TextBlock:

<!-- Hyperlinks combined in the same TextBlock. -->
<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="https://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

Гиперссылки, отображающие TextDecorations

В следующем примере разметки демонстрируется элемент Hyperlink, определенный с подчеркиванием и без него:

<!-- Hyperlink with default underline. -->
<Hyperlink NavigateUri="https://www.msn.com">
  MSN Home
</Hyperlink>

<Run Text=" | " />

<!-- Hyperlink with no underline. -->
<Hyperlink Name="myHyperlink" TextDecorations="None"
           MouseEnter="OnMouseEnter"
           MouseLeave="OnMouseLeave"
           NavigateUri="https://www.msn.com">
  My MSN
</Hyperlink>

В следующей таблице показана производительность отображения 1000 элементов Hyperlink с подчеркиванием и без него.

Гиперссылка

Время создания (мс)

Время отображения (мс)

С подчеркиванием

289

1130

Без подчеркивания

299

776

Возможности форматирования текста

Приложение WPF предоставляет службы форматирования текста RTF, такие как автоматическая расстановка переносов. Эти службы могут влиять на производительность приложения и должны использоваться только при необходимости.

Необходимость избегать необязательной расстановки переносов

Автоматическая расстановка переносов находит точки возможного переноса для строк текста и разрешает дополнительные позиции разрыва строк в объектах TextBlock и FlowDocument. По умолчанию возможность автоматического переноса в этих объектах отключена. Можно включить эту возможность, установив для свойства объекта "IsHyphenationEnabled" значение true. Однако включение этой возможности приводит к тому, что приложение WPF инициирует взаимодействие с компонентом Component Object Model (COM), которое может повлиять на производительность приложения. Рекомендуется не использовать автоматическую расстановку переносов, если это не требуется.

Необходимость соблюдать осторожность при использовании элементов "Figure"

Элемент Figure представляет часть растягиваемого содержимого, которое может быть абсолютно позиционировано внутри страницы содержимого. В некоторых случаях объект Figure может вызвать автоматическое переформатирование всей страницы, если ее положение конфликтует с уже размещенным содержимым. Можно свести к минимуму вероятность ненужного переформатирования либо путем группировки элементов Figure друг за другом, либо объявлением их в верхней части содержимого в сценарии фиксированного размера страницы.

Оптимальный абзац

Средство оптимального абзаца объекта FlowDocument размещает абзацы таким образом, что пробел распределяется равномерно, насколько это возможно. По умолчанию средство оптимального абзаца отключено. Можно включить эту возможность, установив для свойства IsOptimalParagraphEnabled объекта значение true. Однако включение этой возможности влияет на производительность приложения. Рекомендуется не использовать средство оптимального абзаца, если это не требуется.

См. также

Основные понятия

Улучшение производительности приложений WPF

Планирование производительности приложения

Оптимизация производительности. Использование преимуществ аппаратного ускорения

Оптимизация производительности: разметка и разработка

Оптимизация производительности: двумерная графика и обработка изображений

Оптимизация производительности: поведение объекта

Оптимизация производительности: ресурсы приложения

Оптимизация производительности: привязка данных

Оптимизация производительности. Дополнительные рекомендации