Partilhar via


Otimizando o desempenho: texto

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

  1. Usando diretamente os objetos Glyphs e GlyphRun.

  2. Usando o FormattedText objeto.

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

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

Renderização de texto no nível do glifo

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

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

  • Imprimir cenários.

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

    • Gravador de documentos Microsoft XPS.

    • Drivers de impressora anteriores, saída de aplicações Win32 para formato fixo.

    • Formato de spool de impressão.

  • Representação de documentos em formato fixo, incluindo clientes para versões anteriores do Windows e outros dispositivos informáticos.

Observação

Glyphs e GlyphRun são projetados para apresentação de documentos em formato fixo e cenários de impressão. O WPF fornece vários elementos para cenários de layout geral 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 a Tipografia no WPF.

Os exemplos a seguir mostram como definir propriedades para um objeto Glyphs em XAML. Os exemplos pressupõem que as fontes Arial, Courier New e Times New Roman estão instaladas na pasta C:\WINDOWS\Fonts 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 através 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 fácil utilização de formatação de texto rico, que são funcionalidades integradas nos controlos do Windows Presentation Foundation (WPF), como TextBlock e FlowDocument.

Objeto de Texto Formatado

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

Para criar texto formatado, chame o construtor FormattedText para criar um objeto FormattedText. Depois de criar a cadeia de texto formatada inicial, você pode aplicar uma variedade de estilos de formatação. Se seu aplicativo quiser 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 FormattedText .

O FormattedText objeto fornece capacidade de formatação de texto de baixo nível. Você pode aplicar vários estilos de formatação a um ou mais caracteres. Por exemplo, você pode chamar os métodos SetFontSize e SetForegroundBrush para alterar a formatação dos cinco primeiros caracteres do 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

Controlos de FlowDocument, TextBlock e Label

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

O FlowDocument afeta o desempenho mais do que o TextBlock ou o Label

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

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

Evite usar TextBlock no FlowDocument

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

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 Executar para definir propriedades de texto

Em geral, usar um Run dentro de a TextBlock é mais intensivo em desempenho do que não usar um objeto explícito Run . Se você estiver usando um Run para definir propriedades de 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 de apresentar 1000 TextBlock objetos com e sem uma definição explícita Run.

Tipo TextBlock Tempo de criação (ms) Tempo de renderização (ms)
Executar configuração de propriedades de texto 146 540
TextBlock definindo propriedades de texto 43 453

Evite a vinculação de dados à propriedade Label.Content

Imagine um cenário em que tens um Label objeto que é atualizado com frequência de uma String fonte. Quando os dados vinculam a Label propriedade do Content elemento ao String objeto de origem, você pode enfrentar um desempenho insatisfatório. Cada vez que a fonte 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 este problema é simples. Se o Label não estiver definido como um valor personalizado ContentTemplate, substitua o Label por um(a) TextBlock e vincule sua propriedade Text à string de origem.

Propriedade vinculada a dados Tempo de atualização (ms)
Etiqueta.Conteúdo 835 (oitocentos e trinta e cinco)
TextBlock.Text 242

O objeto Hyperlink é um elemento de conteúdo em linha que permite hospedar hiperlinks no 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 que você cria em seu aplicativo. Por exemplo, talvez você queira exibir vários hiperlinks, como os seguintes:

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 se pode adicionar ao texto; no entanto, pode exigir muitos recursos de desempenho para ser instanciado. Se fizer um uso extensivo dos elementos Hyperlink, considere mostrar um sublinhado somente ao acionar um evento, como o evento MouseEnter. 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:

Hiperlinks exibindo Decorações de Texto

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.

Hiperligação 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 só devem ser usados 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 em objetos TextBlock e FlowDocument. Por padrão, o recurso de hifenização automática está desabilitado nesses objetos. Você pode habilitar esse recurso definindo a propriedade IsHyphenationEnabled do objeto como true. No entanto, habilitar esse recurso faz com que o WPF inicie a interoperabilidade do COM (Component Object Model), o que pode afetar o desempenho do aplicativo. Recomenda-se que você não use hifenização automática, a menos que você precise dela.

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 provocar a reformatagem automática de uma página inteira se a sua posição colidir com o conteúdo que já foi disposto. Você pode minimizar a possibilidade de reformatação desnecessária agrupando os elementos Figure próximos uns dos outros ou declarando-os perto da parte superior do conteúdo em um cenário de tamanho de página fixo.

Parágrafo ótimo

A funcionalidade de parágrafo ideal do objeto FlowDocument organiza os parágrafos de modo que o espaço em branco seja distribuído da forma mais uniforme possível. Por padrão, o recurso de parágrafo ideal está desativado. 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 precise dele.

Ver também