Share via


最佳化效能:文字

更新:2007 年 11 月

WPF 透過使用具豐富功能的使用者介面 (UI) 控制項,支援文字內容的呈現。一般而言,您可以將文字呈現分成三層:

  1. 直接使用 GlyphsGlyphRun 物件。

  2. 使用 FormattedText 物件。

  3. 使用高階控制項 (如 TextBlockFlowDocument 物件)。

本主題提供文字呈現的效能建議。

這個主題包含下列章節。

  • 在圖像層次呈現文字
  • FormattedText 物件
  • FlowDocument、TextBlock 和 Label 控制項
  • 超連結
  • 文字格式化功能
  • 相關主題

在圖像層次呈現文字

Windows Presentation Foundation (WPF) 針對想要攔截文字並在格式化之後保留文字的客戶,提供進階的文字支援,包含可以直接存取 Glyphs 的圖像 (Glyph) 層次標記。這些功能提供下列每個案例中之不同文字呈現需求的重要支援。

  • 固定格式文件的螢幕顯示。

  • 列印案例。

    • 可延伸標記語言 (XAML) 做為裝置印表機語言。

    • Microsoft XPS 文件寫作程式。

    • 先前的印表機驅動程式 (從 Win32 應用程式輸出至固定格式)。

    • 列印多工緩衝處理格式。

  • 固定格式文件呈現 (包含舊版 Windows 和其他運算裝置的用戶端)。

注意事項:

GlyphsGlyphRun 是針對固定格式文件呈現和列印案例所設計。Windows Presentation Foundation (WPF) 提供數個項目可用於一般配置和使用者介面 (UI) 案例 (如 LabelTextBlock)。如需配置和 UI 案例的詳細資訊,請參閱 Windows Presentation Foundation 中的印刷樣式

下列範例顯示如何以可延伸標記語言 (XAML) 定義 Glyphs 物件的屬性。Glyphs 物件代表 XAML 格式的 GlyphRun 輸出。這個範例假設 Arial、Courier New 和 Times New Roman 字型已安裝在本機電腦的 C:\WINDOWS\Fonts 資料夾中。

<!-- The example shows how to use a Glyphs object. -->
<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://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>

使用 DrawGlyphRun

如果您擁有自訂控制項,而且想要呈現圖像,請使用 DrawGlyphRun 方法。

WPF 也利用 FormattedText 物件提供自訂文字格式的低階服務。在 Windows Presentation Foundation (WPF) 中呈現文字的最有效方式,是使用 GlyphsGlyphRun 在圖像層次產生文字內容。然而,這項有效性的代價是遺失易用的 Rich Text 格式,這是 Windows Presentation Foundation (WPF) 控制項的內建功能 (如 TextBlockFlowDocument)。

FormattedText 物件

FormattedText 物件可讓您繪製多行文字,文字中的每個字元都可以個別格式化。如需詳細資訊,請參閱繪製格式化的文字

若要建立格式化文字,請呼叫 FormattedText 建構函式 (Constructor) 建立 FormattedText 物件。建立初始格式化文字字串之後,就可以套用某個範圍的格式化樣式。如果應用程式想要實作它自己的配置,則 FormattedText 物件是比使用控制項 (如 TextBlock) 還要好的選擇。如需 FormattedText 物件的詳細資訊,請參閱繪製格式化的文字

FormattedText 物件提供低階文字格式化功能。您可以將多個格式化樣式套用至一個或多個字元。例如,您可以同時呼叫 SetFontSizeSetForegroundBrush 方法,變更文字前五個字元的格式。

下列程式碼範例會建立並呈現 FormattedText 物件。

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));
}

FlowDocument、TextBlock 和 Label 控制項

WPF 包含多個將文字繪製至螢幕的控制項。每個控制項都鎖定不同的案例,而且擁有自己的功能與限制清單。

FlowDocument 對效能的影響大於 TextBlock 或 Label

一般而言,在需要有限的文字支援 (例如使用者介面 (UI) 中的簡短句子) 時,應該使用 TextBlock 項目。而在需要最少文字支援時,則可使用 LabelFlowDocument 項目是支援豐富內容呈現之可重新流動文件的容器,因此對效能的影響也會大於使用 TextBlockLabel 控制項。

如需 FlowDocument 的詳細資訊,請參閱非固定格式文件概觀

避免在 FlowDocument 中使用 TextBlock

TextBlock 項目是衍生自 UIElement。而 Run 項目是衍生自 TextElement,這個的成本低於使用 UIElement 衍生物件。如果可能,請使用 Run,而不要使用 TextBlock 來顯示 FlowDocument 中的文字內容。

下列標記範例說明兩種用來設定 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>

避免使用 Run 設定文字屬性

一般而言,在 TextBlock 內使用 Run 損耗效能的程度會高於根本不使用明確 Run 物件。如果為了設定文字屬性而使用 Run,則請改為將那些屬性直接設定在 TextBlock 上。

下列標記範例說明這兩種用來設定文字屬性的方式,而在這個案例中,是 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>

下表顯示用來顯示具有和沒有明確 Run 之 1000 個 TextBlock 物件的成本。

TextBlock 型別

建立時間 (毫秒)

呈現時間 (毫秒)

設定文字屬性的 Run

146

540

設定文字屬性的 TextBlock

43

453

避免資料繫結至 Label.Content 屬性

想像您在案例中擁有會從 String 來源經常更新的 Label 物件。將 Label 項目的 Content 屬性資料繫結 (Data Binding) 至 String 來源物件時,可能會產生較差的效能。因為 String 物件是不可變的,所以無法進行修改,因此每次更新來源 String 時,都會捨棄舊的 String 物件,並重新建立新的 String。因此會導致 Label 物件的 ContentPresenter 捨棄它的舊內容,並重新產生新內容以顯示新的 String

這個問題的解決方法十分簡單。如果 Label 不是設定為自訂 ContentTemplate 值,請將 Label 取代為 TextBlock,並將它的 Text 屬性資料繫結至來源字串。

資料繫結屬性

更新時間 (毫秒)

Label.Content

835

TextBlock.Text

242

超連結

Hyperlink 物件是內嵌 (Inline) 層級非固定格式內容項目,這個項目可讓您在非固定格式內容中裝載 (Host) 超連結 (Hyperlink)。

結合某個 TextBlock 物件中的超連結

您可以最佳化多個 Hyperlink 項目的使用,方法是將它們分組到相同 TextBlock 內。這有助於將您在應用程式中建立的物件數目降到最低。例如,您可能會想要如下列所示顯示多個超連結:

MSN 首頁 | 我的 MSN

下列標記範例顯示多個用來顯示超連結的 TextBlock 項目:

<!-- Hyperlinks in separate TextBlocks. -->
<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="https://www.msn.com">MSN Home</Hyperlink>
</TextBlock>

<TextBlock Text=" | "/>

<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>

下列標記範例顯示使用單一 TextBlock 顯示超連結的最有效方式:

<!-- Hyperlinks combined in the same TextBlock. -->
<TextBlock>
  <Hyperlink TextDecorations="None" NavigateUri="https://www.msn.com">MSN Home</Hyperlink>

  <Run Text=" | " />

  <Hyperlink TextDecorations="None" NavigateUri="http://my.msn.com">My MSN</Hyperlink>
</TextBlock>

只有 MouseEnter 事件的超連結才顯示底線

TextDecoration 物件是您可以加入至文字的視覺裝飾,但它的具現化 (Instantiate) 處理會損耗效能。如果大量使用 Hyperlink 項目,則請考慮只有在觸發 (Trigger) 事件 (如 MouseEnter 事件) 時才顯示底線。如需詳細資訊,請參閱 HOW TO:使用文字裝飾搭配超連結

MouseEnter 時出現的超連結

顯示 TextDecoration 的超連結

下列標記範例顯示定義為有底線及没有底線的 Hyperlink

<!-- Hyperlink with default underline. -->
<Hyperlink NavigateUri="https://www.msn.com">
  MSN Home
</Hyperlink>

<Run Text=" | " />

<!-- Hyperlink with no underline. -->
<Hyperlink Name="myHyperlink" TextDecorations="None"
           MouseEnter="OnMouseEnter"
           MouseLeave="OnMouseLeave"
           NavigateUri="https://www.msn.com">
  My MSN
</Hyperlink>

下表顯示用來顯示具有和沒有底線之 1000 Hyperlink 個項目的效能成本。

超連結

建立時間 (毫秒)

呈現時間 (毫秒)

具有底線

289

1130

沒有底線

299

776

文字格式化功能

WPF 提供 Rich Text 格式服務 (如自動斷字)。這些服務可能會影響應用程式效能,因此只應該在必要時才使用。

避免使用不必要的斷字

自動斷字會尋找文字行的連字號中斷點,並允許 TextBlockFlowDocument 物件中的行具有額外的中斷位置。在這些物件中,預設會停用自動斷字功能。而將物件的 IsHyphenationEnabled 屬性設定為 true,就可以啟用這個功能。然而,啟用這個功能會導致WPF 啟始 元件物件模型 (COM) 互通性 (Interoperability),這會影響應用程式效能。建議除非必要,否則請不要使用自動斷字。

小心使用 Figure

Figure 項目代表可以以絕對位置放在內容頁面中的非固定格式內容部分。在某些情況下,如果 Figure 的位置與目前已配置的內容衝突,則可能會導致整個頁面自動重新格式化。將 Figure 項目分組成彼此相鄰,而如果是固定頁面大小案例,則在接近內容頂端的位置宣告它們,就可以將不必要重新格式化的可能性降到最少。

最佳段落

FlowDocument 物件的最佳段落功能可以配置段落,以便盡可能均勻地分配空白區。預設會停用最佳段落功能。而將物件的 IsOptimalParagraphEnabled 屬性設定為 true,就可以啟用這個功能。然而,啟用這個功能會影響應用程式效能。建議除非必要,否則請不要使用最佳段落功能。

請參閱

概念

最佳化 WPF 應用程式效能

應用程式效能規劃

最佳化效能:運用硬體

最佳化效能:配置與設計

最佳化效能:2D 圖形和影像處理

最佳化效能:物件行為

最佳化效能:應用程式資源

最佳化效能:資料繫結

最佳化效能:其他建議

WPF 效能工具和資源