Compartir a través de


Optimización del rendimiento: texto

WPF incluye compatibilidad con la presentación de contenido de texto mediante el uso de controles de interfaz de usuario (UI) enriquecidos con características. En general, puede dividir la representación de texto en tres capas:

  1. Usar directamente los objetos Glyphs y GlyphRun.

  2. Uso del FormattedText objeto .

  3. Usar controles de alto nivel, como los objetos TextBlock y FlowDocument.

En este tema se proporcionan recomendaciones de rendimiento de representación de texto.

Representar texto en el nivel de glifo

Windows Presentation Foundation (WPF) proporciona compatibilidad avanzada con texto, incluido el marcado a nivel de glifo con acceso directo a Glyphs para los clientes que desean interceptar y conservar texto después del formato. Estas características proporcionan compatibilidad crítica con los distintos requisitos de representación de texto en cada uno de los escenarios siguientes.

  • Pantalla en la que se muestran los documentos de formato fijo.

  • Escenarios de impresión.

    • Lenguaje de marcado extensible de aplicaciones (XAML) como lenguaje de impresora de dispositivos.

    • Escritor de documentos de Microsoft XPS.

    • Controladores de impresora anteriores, salida de aplicaciones Win32 al formato fijo.

    • Formato de cola de impresión.

  • Representación de documentos de formato fijo, incluidos los clientes para versiones anteriores de Windows y otros dispositivos informáticos.

Nota:

Glyphs y GlyphRun están diseñados para escenarios de impresión y presentación de documentos de formato fijo. WPF proporciona varios elementos para escenarios generales de diseño e interfaz de usuario (UI), como Label y TextBlock. Para obtener más información sobre los escenarios de diseño e interfaz de usuario, vea tipografía en WPF.

En los ejemplos siguientes se muestra cómo definir propiedades para un Glyphs objeto en XAML. En los ejemplos se supone que las fuentes Arial, Courier New y Times New Roman están instaladas en la carpeta C:\WINDOWS\Fonts del equipo 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>

Uso de DrawGlyphRun

Si tiene un control personalizado y desea representar glifos, use el DrawGlyphRun método .

WPF también proporciona servicios de nivel inferior para el formato de texto personalizado mediante el uso del FormattedText objeto . La forma más eficaz de representar texto en Windows Presentation Foundation (WPF) es mediante la generación de contenido de texto en el nivel de glifo mediante Glyphs y GlyphRun. Sin embargo, el costo de esta eficacia es la pérdida de formato de texto enriquecido fácil de usar, que son características integradas de controles de Windows Presentation Foundation (WPF), como TextBlock y FlowDocument.

FormattedText (objeto)

El FormattedText objeto permite dibujar texto de varias líneas, en el que cada carácter del texto se puede formatear individualmente. Para obtener más información, vea Dibujar texto con formato.

Para crear texto con formato, llame al FormattedText constructor para crear un FormattedText objeto . Una vez creada la cadena de texto con formato inicial, puede aplicar un intervalo de estilos de formato. Si la aplicación quiere implementar su propio diseño, el FormattedText objeto es mejor que usar un control, como TextBlock. Para obtener más información sobre el FormattedText objeto, vea Dibujar texto con formato .

El FormattedText objeto proporciona funcionalidad de formato de texto de bajo nivel. Puede aplicar varios estilos de formato a uno o varios caracteres. Por ejemplo, podría llamar a los métodos SetFontSize y SetForegroundBrush para cambiar el formato de los cinco primeros caracteres del texto.

En el siguiente ejemplo de código, se crea un objeto FormattedText y se 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 FlowDocument, TextBlock y Label

WPF incluye varios controles para dibujar texto en la pantalla. Cada control está dirigido a un escenario diferente y tiene su propia lista de características y limitaciones.

FlowDocument afecta al rendimiento más que TextBlock o Label

En general, el TextBlock elemento debe usarse cuando se requiere compatibilidad limitada con texto, como una frase breve en una interfaz de usuario (UI). Label se puede usar cuando se requiere compatibilidad mínima con texto. El FlowDocument elemento es un contenedor para documentos que se pueden volver a fluir que admiten una presentación enriquecida del contenido y, por lo tanto, tiene un mayor impacto en el rendimiento que el uso de los TextBlock controles o Label .

Para obtener más información sobre FlowDocument, vea Información general del Documento de Flujo.

Evitar el uso de TextBlock en FlowDocument

El TextBlock elemento se deriva de UIElement. El Run elemento se deriva de TextElement, que es menos costoso de usar que un UIElementobjeto derivado. Cuando sea posible, use Run en lugar de TextBlock para mostrar contenido de texto en .FlowDocument

En el ejemplo de marcado siguiente se muestran dos formas de establecer el contenido de texto dentro de :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>

Evitar usar Ejecutar para establecer propiedades de texto

En general, el uso de un Run dentro de un TextBlock es más exigente en cuanto al rendimiento que no utilizar un objeto explícito Run en absoluto. Si usa un Run para establecer propiedades de texto, establezca esas propiedades directamente en su TextBlock lugar.

En el ejemplo de marcado siguiente se muestran estas dos maneras de establecer una propiedad de texto, en este caso, la FontWeight propiedad :

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

En la tabla siguiente se muestra el costo de mostrar 1000 TextBlock objetos con y sin un explícito Run.

Tipo TextBlock Hora de creación (ms) Tiempo de representación (ms)
Ejecutar la configuración de las propiedades del texto 146 540
Configuración de propiedades de texto en TextBlock 43 453

Evitar el enlace de datos a la propiedad Label.Content

Imagina un escenario en el que tienes un Label objeto que se actualiza con frecuencia a partir de un String origen. Cuando los datos enlazan la Label propiedad del Content elemento al String objeto de origen, puede experimentar un rendimiento deficiente. Cada vez que se actualiza el origen String , se descarta el objeto antiguo String y se vuelve a crear un nuevo String , ya que un String objeto es inmutable, no se puede modificar. Esto, a su vez, hace que el ContentPresenter del Label objeto descarte su contenido antiguo y vuelva a generar el nuevo contenido para mostrar el nuevo String.

La solución a este problema es sencilla. Si el Label no se establece en un valor personalizado ContentTemplate, reemplace el Label por un TextBlock y vincule su propiedad Text a la cadena de origen.

Propiedad enlazada a datos Hora de actualización (ms)
Label.Content 835
TextBlock.Text 242

El Hyperlink objeto es un elemento de flujo de contenido en línea que permite alojar hipervínculos dentro del flujo de contenido.

Puede optimizar el uso de varios Hyperlink elementos agrupandolos en el mismo TextBlock. Esto ayuda a minimizar el número de objetos que crea en la aplicación. Por ejemplo, puede que desee mostrar varios hipervínculos, como los siguientes:

Inicio de MSN | Mi MSN

En el ejemplo de marcado siguiente se muestran varios TextBlock elementos usados para mostrar los hipervínculos:

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

En el ejemplo de marcado siguiente se muestra una manera más eficaz de mostrar los hipervínculos, esta vez, mediante un ú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>

Un TextDecoration objeto es una ornamentación visual que se puede agregar al texto; sin embargo, puede requerir mucho rendimiento al instanciarlo. Si hace un uso extenso de Hyperlink elementos, considere mostrar un subrayado solo al activar un evento, como el evento MouseEnter. Para obtener más información, vea Especificar si un hipervínculo está subrayado.

En la imagen siguiente se muestra cómo el evento MouseEnter desencadena el hipervínculo subrayado:

Hipervínculos que muestran TextDecorations

En el ejemplo de marcado siguiente se muestra un Hyperlink elemento definido con y sin un subrayado:

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

En la tabla siguiente se muestra el costo de rendimiento de mostrar 1000 Hyperlink elementos con y sin subrayado.

de hipervínculo Hora de creación (ms) Tiempo de representación (ms)
Con subrayado 289 1130
Sin subrayado 299 776

Características de formato de texto

WPF proporciona servicios de formato de texto enriquecido, como divisiones automáticas de palabras. Estos servicios pueden afectar al rendimiento de la aplicación y solo se deben usar cuando sea necesario.

Evitar el uso innecesario de guiones

La división automática busca puntos de interrupción de guion para líneas de texto y permite posiciones de interrupción adicionales para las líneas en TextBlock y FlowDocument objetos. De forma predeterminada, la característica de guionización automática está deshabilitada en estos objetos. Puede habilitar esta característica configurando la propiedad IsHyphenationEnabled del objeto a true. Sin embargo, habilitar esta característica hace que WPF inicie la interoperabilidad del modelo de objetos componentes (COM), lo que puede afectar al rendimiento de la aplicación. Se recomienda no usar la división automática de palabras a menos que lo necesiten.

Use las figuras con cuidado

Un Figure elemento representa una parte del contenido de flujo que se puede colocar absolutamente dentro de una página de contenido. En algunos casos, una Figure puede hacer que una página completa se vuelva a formatear automáticamente si su posición entra en conflicto con el contenido que ya se ha diseñado. Puede minimizar la posibilidad de volver a formatear innecesariamente agrupando Figure elementos entre sí o declarandolos cerca de la parte superior del contenido en un escenario fijo de tamaño de página.

Párrafo óptimo

La característica de párrafo óptima del FlowDocument objeto establece párrafos para que el espacio en blanco se distribuya lo más uniformemente posible. De forma predeterminada, la característica de párrafo óptima está deshabilitada. Puede habilitar esta característica estableciendo la propiedad del IsOptimalParagraphEnabled objeto en true. Sin embargo, habilitar esta característica afecta al rendimiento de la aplicación. Se recomienda no usar la característica de párrafo óptima a menos que la necesite.

Consulte también