Optimieren der Leistung: Text

WPF unterstützt die Präsentation von Textinhalten durch Verwendung von umfangreichen Benutzeroberflächen-Steuerelementen. Im Allgemeinen können Sie das Rendern von Text in drei Ebenen unterteilen:

  1. Verwenden Sie die Objekte Glyphs und GlyphRun direkt.

  2. Verwenden Sie das FormattedText-Objekt.

  3. Verwenden Sie Steuerelementen auf hoher Ebene, z. B. die Objekte TextBlock und FlowDocument.

In diesem Thema erhalten Sie Empfehlungen bezüglich des Renderns von Text.

Rendern von Text auf der Symbolebene

Windows Presentation Foundation (WPF) bietet erweiterte Unterstützung für Text, einschließlich Markup auf Symbolebene mit direktem Zugriff auf Glyphs für Kund*innen, die Text nach der Formatierung abfangen und beibehalten möchten. Diese Funktionen stellen wichtige Unterstützung für verschiedene Text-Rendering-Voraussetzungen in jedem der folgenden Szenarios bereit.

  • Bildschirmanzeige von Dokumenten mit festem Format

  • Druckszenarios

    • XAML (Extensible Application Markup Language) als Gerätedruckersprache.

    • Microsoft XPS-Dokument-Generator.

    • Ältere Druckertreiber geben Win32-Anwendungen in einem festen Format aus.

    • Druckerspooler-Format

  • Darstellung von Dokumenten mit festem Format, einschließlich Clients für vorherige Versionen von Windows und anderen Computergeräten.

Hinweis

Glyphs und GlyphRun sind für die Darstellung von Dokumenten mit festem Format sowie für Druckszenarien konzipiert. WPF bietet mehrere Elemente für allgemeine Layout- und Benutzeroberflächenszenarien wie z. B. Label und TextBlock. Weitere Informationen zu Layout- und Benutzeroberflächenszenarien finden Sie unter Typografie in WPF.

In den folgenden Beispielen wird gezeigt, wie Eigenschaften für ein Glyphs-Objekt in XAML definiert werden. In den Beispielen wird davon ausgegangen, dass die Schriftarten Arial, Courier New und Times New Roman im Ordner C:\WINDOWS\Fonts auf dem lokalen Computer installiert sind.

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

Verwenden von DrawGlyphRun

Wenn Sie über ein benutzerdefiniertes Steuerelement verfügen und Symbole rendern möchten, können Sie die DrawGlyphRun-Methode verwenden.

WPF bietet außerdem Dienste niedriger Ebene für benutzerdefinierte Formatierung von Text durch die Verwendung des FormattedText-Objekts. Am effizientesten rendern Sie Text in WPF (Windows Presentation Foundation), indem Sie Textinhalte auf Symbolebene mit Glyphs und GlyphRun erstellen. Der Preis für diese Effizienz ist jedoch der Verlust der umfangreichen benutzerfreundlichen Textformatierung, die in WPF-Steuerelementen (Windows Presentation Foundation) wie TextBlock und FlowDocument integriert ist.

FormattedText-Objekt

Das FormattedText-Objekt ermöglicht das Zeichnen von mehrzeiligem Text, in dem jedes Zeichen einzeln formatiert werden kann. Weitere Informationen finden Sie unter Drawing Formatted Text (Zeichnen von formatiertem Text).

Verwenden Sie zum Erstellen von formatiertem Text den FormattedText-Konstruktor, um ein FormattedText-Objekt zu erstellen. Nachdem Sie die Anfangszeichenfolge für formatierten Text erstellt haben, können Sie eine Reihe von Formatvorlagen anwenden. Wenn für Ihre Anwendung ein eigenes Layout implementiert werden soll, ist das FormattedText-Objekt eine bessere Wahl als die Verwendung eines Steuerelements wie TextBlock. Weitere Informationen zum FormattedText-Objekt finden Sie unter Zeichnen von formatiertem Text.

Das FormattedText-Objekt stellt Textformatierungsfunktionen auf niedriger Ebene zur Verfügung. Sie können mehrere Formatvorlagen auf ein oder mehrere Zeichen anwenden. So können Sie beispielsweise zum Ändern der Formatierung der ersten fünf Zeichen im Text gleichzeitig die SetFontSize-Methode und die SetForegroundBrush-Methode anwenden.

Im folgenden Codebeispiel wird ein FormattedText-Objekt erstellt und gerendert.

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- und Label-Steuerelemente

WPF enthält zahlreiche Steuerelemente für das Zeichnen von Text auf dem Bildschirm. Jedes Steuerelement ist einem bestimmten Szenario zugeordnet und besitzt eine eigene Liste von Funktionen und Einschränkungen.

FlowDocument wirkt sich mehr auf die Leistung aus als TextBlock oder Label

Im Allgemeinen sollte das TextBlock-Element verwendet werden, wenn eine eingeschränkte Textunterstützung erforderlich ist, z. B. ein kurzer Satz auf einer Benutzeroberfläche. Label kann verwendet werden, wenn minimale Textunterstützung erforderlich ist. Das FlowDocument-Element ist ein Container für anpassbare Flussdokumente, die umfassende Inhaltspräsentationen unterstützen, und wirkt sich daher mehr auf die Leistung aus als die Verwendung der Steuerelemente TextBlock oder Label.

Weitere Informationen zu FlowDocument finden Sie unter Übersicht über Flussdokumente.

Vermeiden von TextBlock in FlowDocument

Das TextBlock-Element wird von UIElement abgeleitet. Das Run-Element wird von TextElement abgeleitet und ist weniger aufwendig als die Verwendung eines abgeleiteten UIElement-Objekts. Verwenden Sie wenn möglich Run anstelle von TextBlock für das Anzeigen von Textinhalten in einem FlowDocument.

Im folgenden Markupbeispiel werden zwei Möglichkeiten zum Festlegen von Textinhalt in einem FlowDocument veranschaulicht:

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

Vermeiden von Run zum Festlegen von Texteigenschaften

Im Allgemeinen ist es ressourcenintensiver, Run in einem TextBlock als überhaupt kein explizites Run-Objekt zu verwenden. Wenn Sie Run verwenden, um Texteigenschaften festzulegen, sollten Sie diese Eigenschaften stattdessen direkt im TextBlock festlegen.

Im folgenden Markupbeispiel werden diese beiden Verfahren zum Festlegen einer Texteigenschaft (in diesem Fall die FontWeight-Eigenschaft) veranschaulicht:

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

In der folgenden Tabelle wird der Ressourcenbedarf für das Anzeigen von 1.000 TextBlock-Objekten mit und ohne ein explizites Run-Objekt gezeigt.

TextBlock-Typ Erstellungszeit (in ms) Renderingzeit (in ms)
Run zum Festlegen von Texteigenschaften 146 540
TextBlock zum Festlegen von Texteigenschaften 43 453

Vermeiden von Datenbindung an die Label.Content-Eigenschaft

Stellen Sie sich ein Szenario vor, in dem ein Label-Objekt häufig von einer String-Quelle aktualisiert wird. Beim Herstellen einer Datenbindung von der Content-Eigenschaft des Label-Elements an das String-Quellobjekt kann es zu Leistungsproblemen kommen. Bei jeder Aktualisierung der String-Quelle wird das alte String-Objekt verworfen und ein neues String-Objekt erstellt, da ein String-Objekt unveränderlich ist. Dies bewirkt wiederum, dass der ContentPresenter des Label-Objekts den alten Inhalt verwirft und den neuen Inhalt zum Anzeigen des neuen String-Objekts neu generiert.

Die Lösung für dieses Problem ist einfach. Wenn das Label nicht auf einen benutzerdefinierten ContentTemplate-Wert festgelegt ist, ersetzen Sie Label durch eine TextBlock und binden die Daten ihrer Text-Eigenschaft an die Quellzeichenfolge.

Datengebundene Eigenschaft Aktualisierungszeit (in ms)
Label.Content 835
TextBlock.Text 242

Das Hyperlink-Objekt ist ein Element für fortlaufenden Inhalt auf Inlineebene, das Ihnen das Hosten von Links im Flussinhalt ermöglicht.

Sie können die Verwendung mehrerer Hyperlink-Elemente optimieren, indem Sie sie innerhalb desselben TextBlock-Objekts gruppieren. Dadurch wird die Anzahl der Objekte minimiert, die Sie in Ihrer Anwendung erstellen. Zum Beispiel kann es vorkommen, dass Sie mehrere Links wie folgt anzeigen möchten:

MSN Home | My MSN

Im folgenden Markupbeispiel werden mehrere TextBlock-Elemente zum Anzeigen der Links verwendet:

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

Im folgenden Markupbeispiel wird eine effizientere Möglichkeit zum Anzeigen der Links mit einem einzigen TextBlock-Element veranschaulicht:

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

Ein TextDecoration-Objekt ist eine visuelle Verzierung, die Sie dem Text hinzufügen können, die Instanziierung kann jedoch ressourcenintensiv sein. Wenn Sie Hyperlink-Elemente sehr viel verwenden, könnten Sie eine Unterstreichung nur bei der Auslösung eines Ereignisses wie dem MouseEnter-Ereignis anzeigen. Weitere Informationen finden Sie unter Specify Whether a Hyperlink is Underlined (Angeben, ob ein Link unterstrichen wird).

Die folgende Abbildung zeigt, wie das MouseEnter-Ereignis den unterstrichenen Link auslöst:

Hyperlinks displaying TextDecorations

Im folgenden Markupbeispiel wird ein mit und ohne Unterstreichung definierter Hyperlink gezeigt:

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

In der folgenden Tabelle werden die Leistungseinbußen für das Anzeigen von 1.000 Hyperlink-Elementen mit und ohne Unterstreichung gezeigt.

Link Erstellungszeit (in ms) Renderingzeit (in ms)
Mit Unterstreichung 289 1130
Ohne Unterstreichung 299 776

Textformatierungsfunktionen

WPF bietet umfangreiche Formatierungsdienste wie die automatische Silbentrennung. Diese Dienste können die Leistung der Anwendung beeinträchtigen und sollten nur bei Bedarf verwendet werden.

Vermeiden von unnötiger Silbentrennung

Die automatische Silbentrennung findet Trennpunkte für Textzeilen und ermöglicht zusätzliche Trennpositionen für Zeilen in TextBlock- und FlowDocument-Objekten. In der Standardeinstellung ist die automatische Silbentrennung in diesen Objekten deaktiviert. Sie können diese Funktion aktivieren, indem Sie die IsHyphenationEnabled-Eigenschaft des Objekts auf true festlegen. Allerdings führt die Aktivierung dieser Funktion dazu, dass WPF die COM-Interoperabilität (Component Object Model) initiiert, was die Leistung der Anwendung beeinträchtigen kann. Es wird empfohlen, die automatische Silbentrennung nur bei Bedarf zu verwenden.

Vorsichtiges Verwenden von Figure-Elementen

Ein Figure-Element stellt einen Teil eines fortlaufenden Inhalts dar, der auf einer Inhaltsseite absolut positioniert werden kann. In einigen Fällen kann eine Figure das automatische Neuformatieren der gesamte Seite auslösen, wenn ihre Position mit Inhalten kollidiert, die bereits angeordnet wurden. Sie können diese unnötigen Neuformatierungen minimieren, indem Sie Figure-Elemente nebeneinander gruppieren oder sie in einem Szenario mit fester Seitengröße am oberen Rand des Inhalts deklarieren.

Optimale Absatzformatierung

Mit der optimalen Absatzformatierung ordnet das FlowDocument-Objekt Absätze so an, dass Leerzeichen möglichst gleichmäßig verteilt werden. In der Standardeinstellung ist die optimale Absatzformatierung deaktiviert. Sie können diese Funktion aktivieren, indem Sie die IsOptimalParagraphEnabled-Eigenschaft des Objekts auf true festlegen. Allerdings beeinträchtigt die Aktivierung dieser Funktion die Leistung der Anwendung. Es wird empfohlen, die optimale Absatzformatierung nur bei Bedarf zu verwenden.

Siehe auch