Otimizando desempenho: texto

O WPF inclui suporte para a apresentação de conteúdo de texto por meio do uso de controles de interface do usuário (UI) ricos em recursos. Em geral, você pode dividir a renderização de texto em três camadas:

  1. Usando os Glyphs objetos e GlyphRun diretamente.

  2. Usando o FormattedText objeto.

  3. Usando controles de alto nível, como os TextBlock objetos e FlowDocument .

Este tópico apresenta recomendações de desempenho de renderização de texto.

Renderização de texto no nível de glifos

O Windows Presentation Foundation (WPF) fornece suporte avançado a texto, incluindo marcação em nível de glifo com acesso direto para clientes que desejam interceptar e manter texto após a Glyphs formatação. Esses recursos dão suporte crítico aos diferentes requisitos de renderização de texto em cada um dos cenários a seguir.

  • Exibição em tela de documentos de formato fixo.

  • Cenários de impressão.

    • XAML (Extensible Application Markup Language) como uma linguagem de impressora de dispositivo.

    • Gravador de documentos Microsoft XPS.

    • Drivers de impressora anteriores, saída de aplicativos Win32 para o formato fixo.

    • Formato do spool de impressão.

  • Representação de documento de formato fixo, incluindo clientes para versões anteriores do Windows e outros dispositivos de computação.

Observação

Glyphs e são projetados para apresentação de documentos em formato fixo e GlyphRun cenários de impressão. O WPF fornece vários elementos para cenários gerais de layout e interface do usuário (UI), como Label e TextBlock. Para obter mais informações sobre cenários de layout e interface do usuário, consulte Tipografia no WPF.

Os exemplos a seguir mostram como definir propriedades para um Glyphs objeto em XAML. Os exemplos assumem que as fontes Arial, Courier New e Times New Roman estão instaladas na pasta C:\WINDOWS\Fontes no computador local.

<!-- 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>

Usando DrawGlyphRun

Se você tiver controle personalizado e quiser renderizar glifos, use o DrawGlyphRun método.

O WPF também fornece serviços de nível inferior para formatação de texto personalizada por meio do uso do FormattedText objeto. A maneira mais eficiente de renderizar texto no Windows Presentation Foundation (WPF) é gerando conteúdo de texto no nível do glifo usando Glyphs e GlyphRun. No entanto, o custo dessa eficiência é a perda da formatação rich text fácil de usar, que são recursos internos dos controles do Windows Presentation Foundation (WPF), como TextBlock e FlowDocument.

Objeto FormattedText

O FormattedText objeto permite desenhar texto de várias linhas, no qual cada caractere no texto pode ser formatado individualmente. Para mais informações, consulte Desenhando texto formatado.

Para criar texto formatado, chame o FormattedText construtor para criar um FormattedText objeto. Após ter criado a cadeia de caracteres de texto formatado inicial, você poderá aplicar uma variedade de estilos de formatação. Se seu aplicativo deseja implementar seu próprio layout, o FormattedText objeto é melhor escolha do que usar um controle, como TextBlock. Para obter mais informações sobre o objeto, consulte Desenhando texto formatado FormattedText .

O FormattedText objeto fornece recurso de formatação de texto de baixo nível. É possível aplicar vários estilos de formatação a um ou mais caracteres. Por exemplo, você pode chamar os SetFontSize métodos e SetForegroundBrush para alterar a formatação dos cinco primeiros caracteres no texto.

O exemplo de código a seguir cria um FormattedText objeto e o renderiza.

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

Controles de rótulo, TextBlock e FlowDocument

WPF inclui vários controles para desenhar texto para a tela. Cada controle é destinado a um cenário diferente e tem sua própria lista de recursos e limitações.

O FlowDocument impacta o desempenho mais do que o TextBlock ou o Rótulo

Em geral, o elemento deve ser usado quando o TextBlock suporte de texto limitado é necessário, como uma breve frase em uma interface do usuário (UI). Label pode ser usado quando o suporte de texto mínimo é necessário. O FlowDocument elemento é um contêiner para documentos refluíveis que oferecem suporte à apresentação avançada de conteúdo e, portanto, tem um impacto de desempenho maior do que o uso dos TextBlock controles ou Label .

Para obter mais informações sobre o , consulte Visão geral do FlowDocumentdocumento de fluxo.

Evite usar TextBlock em FlowDocument

O TextBlock elemento é derivado de UIElement. O Run elemento é derivado de TextElement, que é menos dispendioso de usar do que um UIElementobjeto derivado. Quando possível, use Run em vez de exibir conteúdo de TextBlock texto em um FlowDocumentarquivo .

O exemplo de marcação a seguir ilustra duas maneiras de definir o conteúdo de texto em um 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>

Evite usar Run para definir propriedades de texto

Em geral, usar um dentro de um é mais intensivo em desempenho do que não usar um RunTextBlock objeto explícito Run . Se você estiver usando um para definir propriedades de Run texto, defina essas propriedades diretamente no TextBlock em vez disso.

O exemplo de marcação a seguir ilustra essas duas maneiras de definir uma propriedade text, neste caso, a FontWeight propriedade:

<!-- 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>

A tabela a seguir mostra o custo da exibição de 1000 TextBlock objetos com e sem um Runarquivo .

Tipo TextBlock Tempo de criação (ms) Tempo de renderização (ms)
Propriedades de texto de configuração Run 146 540
Propriedades de texto de configuração TextBlock 43 453

Evite a associação de dados com a propriedade Label.Content

Imagine um cenário em que você tenha um Label objeto que é atualizado com frequência de uma String fonte. Quando os dados vinculam a Label propriedade do elemento ao String objeto de Content origem, você pode enfrentar um desempenho ruim. Cada vez que a origem String é atualizada, o objeto antigo String é descartado e um novo String é recriado — como um String objeto é imutável, ele não pode ser modificado. Isso, por sua vez, faz com que o ContentPresenterLabel objeto descarte seu conteúdo antigo e regenere o novo conteúdo para exibir o novo String.

A solução para esse problema é simples. Se o não estiver definido como um valor personalizadoContentTemplate, substitua o LabelLabel por um TextBlock e os dados vinculam sua Text propriedade à cadeia de caracteres de origem.

Propriedade associada de dados Tempo de atualização (ms)
Label.Content 835
TextBlock.Text 242

O Hyperlink objeto é um elemento de conteúdo de fluxo embutido que permite hospedar hiperlinks dentro do conteúdo de fluxo.

Você pode otimizar o uso de vários Hyperlink elementos agrupando-os dentro do mesmo TextBlock. Isso ajuda a minimizar o número de objetos criados em seu aplicativo. Por exemplo, você talvez queira exibir vários hiperlinks, como o seguinte:

Página inicial do MSN | Meu MSN

O exemplo de marcação a seguir mostra vários TextBlock elementos usados para exibir os hiperlinks:

<!-- 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>

O exemplo de marcação a seguir mostra uma maneira mais eficiente de exibir os hiperlinks, desta vez, usando um único 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>

Um TextDecoration objeto é uma ornamentação visual que você pode adicionar ao texto, no entanto, pode ser um desempenho intensivo para instanciar. Se você fizer uso extensivo de Hyperlink elementos, considere mostrar um sublinhado somente ao acionar um evento, como o MouseEnter evento. Para obter mais informações, consulte Especificar se um hiperlink está sublinhado.

A imagem a seguir mostra como o evento MouseEnter dispara o hiperlink sublinhado:

Hyperlinks displaying TextDecorations

O exemplo de marcação a seguir mostra um Hyperlink definido com e sem sublinhado:

<!-- 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>

A tabela a seguir mostra o custo de desempenho da exibição de 1000 Hyperlink elementos com e sem sublinhado.

Hiperlink Tempo de criação (ms) Tempo de renderização (ms)
Com sublinhado 289 1130
Sem sublinhado 299 776

Recursos de formatação de texto

O WPF fornece serviços de formatação rich text, como hifenizações automáticas. Esses serviços podem afetar o desempenho do aplicativo e devem ser usados somente quando necessário.

Evite o uso desnecessário de hifenização

A hifenização automática localiza pontos de interrupção de hífen para linhas de texto e permite posições de quebra adicionais para linhas e TextBlockFlowDocument objetos. Por padrão, o recurso de hifenização automática está desabilitado nesses objetos. Você pode habilitar esse recurso configurando a propriedade IsHyphenationEnabled do objeto como true. No entanto, habilitar esse recurso faz com que o WPF inicie a interoperabilidade COM (Component Object Model), o que pode afetar o desempenho do aplicativo. É recomendável que você não use a hifenização automática, a menos que necessário.

Use as figuras com cuidado

Um Figure elemento representa uma parte do conteúdo de fluxo que pode ser posicionada de forma absoluta dentro de uma página de conteúdo. Em alguns casos, um Figure pode fazer com que uma página inteira seja reformatada automaticamente se sua posição colidir com o conteúdo que já foi criado. Você pode minimizar a possibilidade de reformatação desnecessária agrupando Figure elementos próximos uns dos outros ou declarando-os próximos à parte superior do conteúdo em um cenário de tamanho de página fixo.

Parágrafo ideal

O recurso de parágrafo ideal do objeto estabelece parágrafos para que o FlowDocument espaço em branco seja distribuído da forma mais uniforme possível. Por padrão, o recurso de parágrafo otimizado é desabilitado. Você pode habilitar esse recurso definindo a propriedade do IsOptimalParagraphEnabled objeto como true. No entanto, habilitar esse recurso afeta o desempenho do aplicativo. É recomendável que você não use o recurso de parágrafo ideal, a menos que necessário.

Confira também