XAML 中的泛空白字元處理
XAML 的語言規則陳述 XAML 處理器實作必須處理的重要空白字元。 本主題說明這些 XAML 語言規則,以及 XAML 處理器的 Windows Presentation Foundation (WPF) 實作所定義的其他空白字元處理,還有用於序列化 (Serialization) 的 XAML 寫入器。
這個主題包含下列章節。
- 空白字元定義
- 空白字元正規化
- 內部文字和基本字串中的空白字元
- 保留空白字元
- 東亞字元
- 空白字元和文字內容模型
- 相關主題
空白字元定義
跟 XML 一致,XAML 中的空白字元有空白、換行字元和定位字元。 這些分別會對應到 Unicode 值 0020、000A 和 0009。
空白字元正規化
根據預設,當 XAML 處理器處理 XAML 檔案時會發生下列空白字元的正規化:
會移除東亞字元間的換行字元。 請參閱本主題後面<東亞字元>一節中有關這個詞彙的定義。
所有空白字元 (空白、換行字元、定位字元) 會轉換為空白。
會刪除所有連續的空白,並取代為單一空白。
會刪除緊接在開頭標記後的空白。
會刪除緊接在結束標記前的空白。
「預設」會對應到 xml:space 屬性 (Attribute) 的預設值所表示的狀態。
內部文字和基本字串中的空白字元
前述正規化規則適用於 XAML 項目內的內部文字。 完成正規化後,XAML 處理器會依據下列情況將任何內部文字轉換為適當的型別:
如果屬性型別不是集合,但不是直接的 Object 型別,XAML 處理器會嘗試使用該型別的型別轉換子 (Type Converter) 進行轉換。 在這裡失敗的轉換會導致編譯時期錯誤。
如果屬性型別是集合,且內部文字是連續的 (沒有介入的項目標記),內部文字會剖析為單一 String。 如果集合型別不接受 String,這也會導致編譯時期錯誤。
如果屬性型別是 Object,則內部文字會剖析為單一 String。 如果有介入的項目標記,這會導致編譯時期錯誤,因為 Object 型別即意味著單一物件 (String 或其他)。
如果屬性型別是集合,而內部文字不是連續的,則第一個子字串會轉換成 String 並加入做為集合項目、介入的項目也會加入做為集合項目,而最後的結尾字串 (如果有的話) 會加入做為集合的第三個 String 項目。
保留空白字元
有幾種技巧可以保留來源 XAML 中最後要展示的空白字元,而不會受 XAML 處理器空白字元正規化的影響。
xml:space="preserve":在項目層級想要保留空白字元的地方指定這個屬性。 這樣會保留所有的空白字元,包含程式碼編輯應用程式為了在視覺上呈現直覺化巢狀結構基於美觀對齊項目而加入的空白。 但是,這些空白呈現與否是由包含項目的內容模型所決定。 避免在根項目層級指定 xml:space="preserve",因為不論您如何設定屬性,大部分的物件模型都不會將空白字元視為必要。 全域設定 xml:space 可能會對某些實作中的 XAML 處理 (尤其是序列化) 帶來效能影響。 比較好的作法是,只有當該項目層級會轉譯字串內的空白字元或是需要空白字元的集合,才特別設定這個屬性。
實體和不分行空格:XAML 支援將任何 Unicode 實體放置在文字物件模型內。 您可以使用專屬的實體,例如不分行空格 (UTF-8 編碼中的  )。 您也可以使用支援不分行空格字元的 Rich Text 控制項。 如果您使用實體來模擬縮排這類的配置特性,應該要特別小心,因為實體在執行階段的輸出會隨著非常多的因素而異,比在典型版面配置系統 (例如面板和邊界的適當使用) 中產生縮排結果的功能複雜許多。 例如,實體會因應使用者的字型選取項目,對應到字型並變更大小。
東亞字元
「東亞字元」是以 Unicode 字元集定義的,範圍從 U+20000 到 U+2FFFD 以及從 U+30000 到 U+3FFFD。 這個子集有時候也稱為「CJK 表意字元」。 如需詳細資訊,請參閱 http://www.unicode.org。
空白字元和文字內容模型
實際上,保留空白字元只是考量所有可能的內容模型子集。 組成該子集的內容模型可以採用單一子句 String 型別的某種型式:一個專屬的 String 集合,或是 String 和其他 IList 或 ICollection<T> 集合中型別的混合。
WPF 中的空白字元和文字內容模型
為方便示範,本節的後續部分將參考 WPF 所定義的特定型別。 本主題說明的空白字元處理功能通常同時與 .NET Framework XAML 服務和 WPF 有關。 若要觀察這種行為的運作情形,您可以使用某個 WPF XAML 標記進行實驗,並在物件圖形中檢視結果,然後再重新序列化為標記。
對於可以採用字串的內容模型的事件,在這些內容模型內的預設行為是:任何保留的空白字元都不會視為必要的。 例如,ListBox 會接受 IList,但不會保留和呈現空白字元 (例如每個 ListBoxItem 間的換行字元)。 如果您嘗試使用換行字元做為 ListBoxItem 項目字串間的分隔符號,便完全無法運作;以換行字元區隔的字串會視為是單一字串和單一項目。
那些會將空白字元視為必要項目的集合,通常是非固定格式文件模型的一部分。 支援空白字元保留行為的主要集合是 InlineCollection。 這個集合類別是使用 WhitespaceSignificantCollectionAttribute 宣告的,當有這個屬性時,XAML 處理器會將集合內的空白字元視為必要的。 在以 WhitespaceSignificantCollectionAttribute 表示的集合內,xml:space="preserve" 和空白字元的結合就會保留和轉譯所有空白字元。 WhitespaceSignificantCollectionAttribute 內 xml:space="default" 和空白字元的結合會進行前述的初始空白字元正規化,也就是在某些位置留下單一空格,然後再保留和轉譯這些空格。 想要使用哪一種行為是由您決定的,而您應該選擇性地使用 xml:space 以啟用您想要的行為。
此外,非固定格式文件模型中某些代表分行符號的內嵌 (Inline) 項目,即使在需要空白字元的集合中,也應該刻意不採納額外的空白。 例如,LineBreak 項目與 HTML 中的 <BR/> 標記 (Tag) 具有相同目的,而基於標記 (Markup) 可讀性,通常 LineBreak 會以撰寫的換行符號與任何接續的文字區隔開來。 該換行符號不應該正規化為接續下一行的前置空白。 若要啟用該行為,LineBreak 項目的類別定義要套用 TrimSurroundingWhitespaceAttribute,然後由 XAML 處理器解譯為 LineBreak 周圍的空白字元一定要修剪。