Condividi tramite


Ottimizzazione delle prestazioni: testo

WPF include il supporto per la presentazione del contenuto di testo attraverso l'uso di controlli avanzati dell'interfaccia utente (UI). In generale, è possibile dividere il rendering del testo in tre livelli:

  1. Uso diretto degli oggetti Glyphs e GlyphRun.

  2. Utilizzo dell'oggetto FormattedText.

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

In questo argomento vengono fornite indicazioni sulle prestazioni per il rendering del testo.

Rendering del testo a livello di glifo

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

  • Visualizzazione su schermo di documenti in formato fisso.

  • Scenari di stampa.

    • XAML (Extensible Application Markup Language) utilizzato come linguaggio per dispositivi di stampa.

    • Scrittore di documenti XPS di Microsoft.

    • I driver precedenti della stampante fornivano l'output delle applicazioni Win32 in formato fisso.

    • Formato coda di stampa.

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

Annotazioni

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 ulteriori informazioni sugli scenari di layout e UI, vedere la Tipografia in WPF.

Gli esempi seguenti illustrano come definire le proprietà per un oggetto Glyphs in XAML. Gli esempi presuppongono 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 metodo DrawGlyphRun.

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 dell'uso facile della formattazione di testo avanzata, che è una funzionalità predefinita dei controlli di Windows Presentation Foundation (WPF), come TextBlock e FlowDocument.

Oggetto di testo formattato

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

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

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

Nell'esempio di codice seguente viene creato un oggetto FormattedText 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 ha un proprio elenco di funzionalità e limitazioni.

FlowDocument influisce sulle prestazioni più di 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 maggiore sulle prestazioni rispetto all'uso dei controlli TextBlock o Label.

Per altre informazioni su FlowDocument, vedere Flow Document Overview.

Evitare di usare TextBlock in FlowDocument

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

L'esempio di markup seguente illustra due modi per impostare il contenuto di testo all'interno di un 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>

Evitare di usare Run per impostare le proprietà del testo

In generale, l'uso di un Run all'interno di un TextBlock richiede più risorse rispetto a non utilizzare affatto un oggetto Run esplicito. Se si usa un Run per impostare le proprietà di testo, impostare tali proprietà direttamente sul TextBlock.

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

<!-- 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 della visualizzazione di 1000 oggetti TextBlock con e senza un Runesplicito.

tipo di TextBlock tempo di creazione (ms) Tempo di rendering (ms)
Configurazione delle impostazioni di esecuzione del testo 146 540
Impostazione delle proprietà di testo del TextBlock 43 453

Evitare l'associazione dati alla proprietà Label.Content

Si supponga di avere un oggetto Label che viene aggiornato di frequente da un'origine String. Quando si esegue il data binding della proprietà Label dell'elemento Content all'oggetto di origine String, è possibile che si verifichino prestazioni scarse. Ogni volta che il String di origine viene aggiornato, l'oggetto String precedente viene rimosso e viene ricreato un nuovo String, perché un oggetto String non è modificabile, non può essere modificato. Questo, a sua volta, fa sì che il ContentPresenter dell'oggetto Label elimini il contenuto precedente e rigeneri il nuovo contenuto per visualizzare il nuovo String.

La soluzione a questo problema è semplice. Se il Label non è impostato su un valore di ContentTemplate personalizzato, sostituire il Label con un TextBlock e associare la relativa proprietà Text alla stringa di origine.

proprietà collegata ai dati ora di aggiornamento (ms)
Etichetta.Contenuto 835
TextBlock.Text 242

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

È possibile ottimizzare l'uso di più elementi Hyperlink raggruppandoli all'interno dello stesso TextBlock. Ciò consente di ridurre al minimo il numero di oggetti creati nell'applicazione. Ad esempio, è possibile visualizzare più collegamenti ipertestuali, ad esempio:

MSN Home | Il mio MSN

L'esempio di markup seguente mostra più elementi TextBlock 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 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 oggetto TextDecoration è un ornamento visivo che è possibile aggiungere al testo; tuttavia, può richiedere molte risorse per essere istanziato. Se si utilizza ampiamente gli elementi Hyperlink, è consigliabile visualizzare una sottolineatura solo quando si attiva un evento, ad esempio l'evento MouseEnter. Per ulteriori informazioni, vedere Specificare se un collegamento ipertestuale è sottolineato.

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

Collegamenti ipertestuali che visualizzano decorazioni di testo

L'esempio di markup seguente mostra un Hyperlink 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 elementi Hyperlink con e senza sottolineatura.

collegamento ipertestuale 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 di testo ricco, come la divisione automatica in sillabe. Questi servizi possono influire sulle prestazioni dell'applicazione e devono essere usati solo quando necessario.

Evitare l'uso non necessario della sillabazione

La sillabazione automatica individua i punti di divisione per i trattini nelle righe di testo e consente posizioni di interruzione aggiuntive per le righe negli oggetti TextBlock e FlowDocument. Per impostazione predefinita, la funzionalità di sillabazione automatica è disabilitata in questi oggetti. È possibile abilitare 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 non usare la sillabazione automatica a meno che non sia necessaria.

Utilizzare le figure con attenzione

Un elemento Figure rappresenta una parte del contenuto del flusso che può essere assolutamente posizionato all'interno di una pagina di contenuto. In alcuni casi, un Figure può causare la riformattazione automatica di un'intera pagina se la posizione si scontra con il contenuto già disposto. È possibile ridurre al minimo la possibilità di riformattamento non necessario raggruppando Figure 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 ottimale del paragrafo 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 è disabilitata. È possibile abilitare questa funzionalità impostando la proprietà IsOptimalParagraphEnabled dell'oggetto su true. Tuttavia, l'abilitazione di questa funzionalità influisce sulle prestazioni dell'applicazione. È consigliabile non utilizzare la funzionalità di paragrafo ottimale, a meno che non sia necessaria.

Vedere anche