Ottimizzazione delle prestazioni: testo

WPF include il supporto per la presentazione del contenuto di testo tramite l'uso di controlli dell'interfaccia utente avanzata dalle funzionalità. In generale, è possibile suddividere il rendering del testo in tre livelli:

  1. Uso diretto degli Glyphs oggetti e GlyphRun .

  2. Utilizzo dell'oggetto FormattedText .

  3. Uso di controlli di alto livello, ad esempio gli TextBlock oggetti e FlowDocument .

Questo argomento offre utili suggerimenti sulle prestazioni del rendering del testo.

Rendering del testo a livello di glifo

Windows Presentation Foundation (WPF) offre supporto di testo avanzato, incluso il markup a livello di glifo con accesso diretto a Glyphs per i clienti che vogliono intercettare e rendere persistente il testo dopo la formattazione. Queste funzionalità forniscono il supporto fondamentale per i diversi requisiti di rendering del testo in ognuno degli scenari seguenti.

  • Visualizzazione di documenti a formato fisso.

  • Scenari di stampa.

    • Xaml (Extensible Application Markup Language) come linguaggio di stampante del dispositivo.

    • Writer di documenti Di Microsoft XPS.

    • Driver della stampante precedenti, output dalle applicazioni Win32 al formato fisso.

    • Formato dello spooling di stampa.

  • Rappresentazione di documenti in formato fisso, inclusi i client per le versioni precedenti di Windows e altri dispositivi di elaborazione.

Nota

Glyphs e GlyphRun sono progettati per scenari di presentazione e stampa di documenti in formato fisso. WPF offre diversi elementi per scenari generali di layout e interfaccia utente , ad esempio Label e TextBlock. Per altre informazioni sugli scenari di layout e interfaccia utente, vedere Tipografia in WPF.

Gli esempi seguenti illustrano come definire le proprietà per un Glyphs oggetto in XAML. Negli esempi si presuppone che i tipi di carattere Arial, Courier New e Times New Roman siano installati nella cartella C:\WINDOWS\Fonts nel computer locale.

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

Se si dispone di un controllo personalizzato e si desidera eseguire il rendering dei glifi, usare il DrawGlyphRun metodo .

WPF offre anche servizi di livello inferiore per la formattazione di testo personalizzata tramite l'uso dell'oggetto FormattedText . Il modo più efficiente per eseguire il rendering del testo in Windows Presentation Foundation (WPF) consiste nel generare contenuto di testo a livello di glifo usando Glyphs e GlyphRun. Tuttavia, il costo di questa efficienza è la perdita di facile uso della formattazione rtf, che sono funzionalità predefinite dei controlli Windows Presentation Foundation (WPF), ad esempio TextBlock e FlowDocument.

Oggetto FormattedText

L'oggetto FormattedText consente di disegnare testo su più righe, in cui ogni carattere del testo può essere formattato singolarmente. Per altre informazioni, vedere Disegno di testo formattato.

Per creare testo formattato, chiamare il FormattedText costruttore per creare un FormattedText oggetto . Dopo aver creato la stringa di testo formattato iniziale, è possibile applicare una gamma di stili di formattazione. Se l'applicazione vuole implementare il proprio layout, l'oggetto è la scelta migliore rispetto all'uso FormattedText di un controllo, ad esempio TextBlock. Per altre informazioni sull'oggetto FormattedText , vedere Disegno di testo formattato.

L'oggetto FormattedText offre funzionalità di formattazione del testo di basso livello. È possibile applicare vari stili di formattazione a uno o più caratteri. Ad esempio, è possibile chiamare entrambi i SetFontSize metodi e SetForegroundBrush per modificare la formattazione dei primi cinque caratteri nel testo.

Nell'esempio di codice seguente viene creato un FormattedText oggetto ed eseguito il rendering.

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

Controlli FlowDocument, TextBlock e Label

WPF include più controlli per disegnare testo sullo schermo. Ogni controllo è destinato a uno scenario diverso e dispone di un proprio elenco di funzionalità e limitazioni.

Un elemento FlowDocument influisce sulle prestazioni più di un elemento TextBlock o Label

In generale, l'elemento TextBlock deve essere usato quando è necessario un supporto di testo limitato, ad esempio una breve frase in un'interfaccia utente. Label può essere usato quando è necessario un supporto di testo minimo. L'elemento FlowDocument è un contenitore per documenti scorrevoli che supportano una presentazione completa di contenuto e pertanto ha un impatto sulle prestazioni maggiore rispetto all'uso dei TextBlock controlli o Label .

Per altre informazioni su , vedere Cenni preliminari sui FlowDocumentdocumenti di Flow.

Evitare di usare TextBlock in FlowDocument

L'elemento TextBlock è derivato da UIElement. L'elemento Run è derivato da TextElement, che è meno costoso da usare rispetto a un UIElementoggetto derivato da . Quando possibile, usare Run anziché TextBlock per visualizzare il contenuto di testo in un oggetto FlowDocument.

L'esempio di markup seguente illustra due modi per impostare il contenuto di testo all'interno di un FlowDocumentoggetto :

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

Evitare di usare un oggetto Run per impostare proprietà di testo

In generale, l'uso di un Run oggetto all'interno di è TextBlock più intensivo delle prestazioni rispetto all'uso di un oggetto esplicito Run . Se si usa un Run oggetto per impostare le proprietà di testo, impostare tali proprietà direttamente sull'oggetto TextBlock .

L'esempio di markup seguente illustra questi due modi per impostare una proprietà di testo, in questo caso la FontWeight proprietà :

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

Nella tabella seguente viene illustrato il costo di visualizzazione di 1000 TextBlock oggetti con e senza un oggetto esplicito Run.

Tipo di TextBlock Tempo di creazione (ms) Tempo di rendering (ms)
Proprietà di testo impostate con Run 146 540
Proprietà di testo impostate con TextBlock 43 453

Evitare di eseguire il data binding alla proprietà Label.Content

Si immagini uno scenario in cui si dispone di un Label oggetto che viene aggiornato di frequente da un'origine String . Quando si associa la Label proprietà dell'elemento Content all'oggetto String di origine, è possibile che si verifichino prestazioni scarse. Ogni volta che l'origine String viene aggiornata, l'oggetto precedente String viene rimosso e viene ricreato un nuovo String oggetto, perché un String oggetto non è modificabile, non può essere modificato. In questo modo, a sua volta, fa sì che l'oggetto ContentPresenter dell'oggetto Label elimini il contenuto precedente e rigenera il nuovo contenuto per visualizzare il nuovo Stringoggetto .

La soluzione di questo problema è semplice. Se l'oggetto Label non è impostato su un valore personalizzato ContentTemplate , sostituire con Label un TextBlock oggetto e associarne Text la proprietà alla stringa di origine.

Proprietà con data binding Tempo di aggiornamento (ms)
Label.Content 835
TextBlock.Text 242

L'oggetto Hyperlink è un elemento di contenuto del flusso inline che consente di ospitare collegamenti ipertestuali all'interno del contenuto del flusso.

È possibile ottimizzare l'uso di più Hyperlink elementi raggruppandoli all'interno dello stesso TextBlockoggetto . In questo modo, è possibile ridurre al minimo il numero di oggetti creati nell'applicazione. È possibile, ad esempio, che si voglia visualizzare più collegamenti ipertestuali, come illustrato di seguito:

Msn Home | My MSN

L'esempio di markup seguente mostra più TextBlock elementi usati per visualizzare i collegamenti ipertestuali:

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

L'esempio di markup seguente mostra un modo più efficiente per visualizzare i collegamenti ipertestuali, questa volta, usando un singolo TextBlockoggetto :

<!-- 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 oggetto è un ornamento visivo che è possibile aggiungere al testo, ma può essere intensivo per le prestazioni per creare un'istanza. Se si usa ampiamente gli Hyperlink elementi, è consigliabile visualizzare una sottolineatura solo quando si attiva un evento, ad esempio l'evento MouseEnter . Per altre informazioni, vedere Specificare se un collegamento ipertestuale è sottolineato.

L'immagine seguente mostra come l'evento MouseEnter attiva il collegamento ipertestuale sottolineato:

Hyperlinks displaying TextDecorations

L'esempio di markup seguente mostra un Hyperlink oggetto definito con e senza sottolineatura:

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

La tabella seguente illustra il costo delle prestazioni della visualizzazione di 1000 Hyperlink elementi con e senza sottolineatura.

Hyperlink Tempo di creazione (ms) Tempo di rendering (ms)
Con sottolineatura 289 1130
Senza sottolineatura 299 776

Funzionalità di formattazione del testo

WPF offre servizi di formattazione rtf, ad esempio trattini automatici. Questi servizi possono influire sulle prestazioni dell'applicazione e devono essere usati solo se strettamente necessario.

Evitare l'uso non necessario della sillabazione

La sillabazione automatica trova punti di interruzione trattini per le righe di testo e consente posizioni di interruzione aggiuntive per le righe in TextBlock e FlowDocument gli oggetti . Per impostazione predefinita, la funzionalità di sillabazione automatica è disattivata in questi oggetti. È possibile attivare questa funzionalità impostando la proprietà IsHyphenationEnabled dell'oggetto su true. Tuttavia, l'abilitazione di questa funzionalità fa sì che WPF avvii l'interoperabilità COM (Component Object Model), che può influire sulle prestazioni dell'applicazione. È consigliabile quindi usare la sillabazione automatica solo se necessario.

Usare con attenzione gli elementi Figure

Un Figure elemento rappresenta una parte del contenuto del flusso che può essere assolutamente posizionato all'interno di una pagina di contenuto. In alcuni casi, un oggetto Figure può causare la riformattazione automatica di un'intera pagina se la sua posizione si scontra con il contenuto già disposto. È possibile ridurre al minimo la possibilità di riformattamento non necessario raggruppando Figure gli elementi uno accanto all'altro o dichiarandoli vicino alla parte superiore del contenuto in uno scenario di dimensioni di pagina fisse.

Paragrafo ottimale

La caratteristica di paragrafo ottimale dell'oggetto FlowDocument dispone i paragrafi in modo che lo spazio vuoto venga distribuito nel modo più uniforme possibile. Per impostazione predefinita, la funzionalità di paragrafo ottimale è disattivata. È possibile abilitare questa funzionalità impostando la proprietà dell'oggetto IsOptimalParagraphEnabled su true. L'attivazione di questa funzionalità, tuttavia, influisce sulle prestazioni dell'applicazione. È consigliabile quindi usare la funzionalità di paragrafo ottimale solo se necessario.

Vedi anche