最佳化效能:文字
更新:2007 年 11 月
WPF 透過使用具豐富功能的使用者介面 (UI) 控制項,支援文字內容的呈現。一般而言,您可以將文字呈現分成三層:
使用 FormattedText 物件。
使用高階控制項 (如 TextBlock 和 FlowDocument 物件)。
本主題提供文字呈現的效能建議。
這個主題包含下列章節。
- 在圖像層次呈現文字
- FormattedText 物件
- FlowDocument、TextBlock 和 Label 控制項
- 超連結
- 文字格式化功能
- 相關主題
在圖像層次呈現文字
Windows Presentation Foundation (WPF) 針對想要攔截文字並在格式化之後保留文字的客戶,提供進階的文字支援,包含可以直接存取 Glyphs 的圖像 (Glyph) 層次標記。這些功能提供下列每個案例中之不同文字呈現需求的重要支援。
固定格式文件的螢幕顯示。
列印案例。
可延伸標記語言 (XAML) 做為裝置印表機語言。
Microsoft XPS 文件寫作程式。
先前的印表機驅動程式 (從 Win32 應用程式輸出至固定格式)。
列印多工緩衝處理格式。
固定格式文件呈現 (包含舊版 Windows 和其他運算裝置的用戶端)。
注意事項: |
---|
Glyphs 和 GlyphRun 是針對固定格式文件呈現和列印案例所設計。Windows Presentation Foundation (WPF) 提供數個項目可用於一般配置和使用者介面 (UI) 案例 (如 Label 和 TextBlock)。如需配置和 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) 中呈現文字的最有效方式,是使用 Glyphs 和 GlyphRun 在圖像層次產生文字內容。然而,這項有效性的代價是遺失易用的 Rich Text 格式,這是 Windows Presentation Foundation (WPF) 控制項的內建功能 (如 TextBlock 和 FlowDocument)。
FormattedText 物件
FormattedText 物件可讓您繪製多行文字,文字中的每個字元都可以個別格式化。如需詳細資訊,請參閱繪製格式化的文字。
若要建立格式化文字,請呼叫 FormattedText 建構函式 (Constructor) 建立 FormattedText 物件。建立初始格式化文字字串之後,就可以套用某個範圍的格式化樣式。如果應用程式想要實作它自己的配置,則 FormattedText 物件是比使用控制項 (如 TextBlock) 還要好的選擇。如需 FormattedText 物件的詳細資訊,請參閱繪製格式化的文字。
FormattedText 物件提供低階文字格式化功能。您可以將多個格式化樣式套用至一個或多個字元。例如,您可以同時呼叫 SetFontSize 和 SetForegroundBrush 方法,變更文字前五個字元的格式。
下列程式碼範例會建立並呈現 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 項目。而在需要最少文字支援時,則可使用 Label。FlowDocument 項目是支援豐富內容呈現之可重新流動文件的容器,因此對效能的影響也會大於使用 TextBlock 或 Label 控制項。
如需 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 時出現的超連結
下列標記範例顯示定義為有底線及没有底線的 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 格式服務 (如自動斷字)。這些服務可能會影響應用程式效能,因此只應該在必要時才使用。
避免使用不必要的斷字
自動斷字會尋找文字行的連字號中斷點,並允許 TextBlock 和 FlowDocument 物件中的行具有額外的中斷位置。在這些物件中,預設會停用自動斷字功能。而將物件的 IsHyphenationEnabled 屬性設定為 true,就可以啟用這個功能。然而,啟用這個功能會導致WPF 啟始 元件物件模型 (COM) 互通性 (Interoperability),這會影響應用程式效能。建議除非必要,否則請不要使用自動斷字。
小心使用 Figure
Figure 項目代表可以以絕對位置放在內容頁面中的非固定格式內容部分。在某些情況下,如果 Figure 的位置與目前已配置的內容衝突,則可能會導致整個頁面自動重新格式化。將 Figure 項目分組成彼此相鄰,而如果是固定頁面大小案例,則在接近內容頂端的位置宣告它們,就可以將不必要重新格式化的可能性降到最少。
最佳段落
FlowDocument 物件的最佳段落功能可以配置段落,以便盡可能均勻地分配空白區。預設會停用最佳段落功能。而將物件的 IsOptimalParagraphEnabled 屬性設定為 true,就可以啟用這個功能。然而,啟用這個功能會影響應用程式效能。建議除非必要,否則請不要使用最佳段落功能。