XAML 型別轉換子概觀
型別轉換子可提供邏輯,以供物件寫入器從 XAML 標記中的字串轉換至物件圖形中的特定物件。 在 .NET Framework XAML 服務中,型別轉換子必須是衍生自 TypeConverter 的類別。 有些轉換子也支援 XAML 儲存路徑,而且可用來將物件序列化成序列化標記中的字串形式。 本主題說明在 XAML 中叫用型別轉換子的方式和時機,並針對 TypeConverter 的方法覆寫提供實作建議。
這個主題包含下列章節。
- 型別轉換概念
- 實作型別轉換子
- 套用 TypeConverterAttribute
- 從標記延伸實作存取服務提供者內容
- XAML 節點資料流中的型別轉換子
- 相關主題
型別轉換概念
以下幾節將提供一些基本概念,以說明 XAML 使用字串的方式,以及 .NET Framework XAML 服務中的物件寫入器如何使用型別轉換子處理某些在 XAML 來源中出現的字串值。
XAML 和字串值
當您在 XAML 檔案中設定屬性值時,該值的初始型別從一般角度看是字串,從 XML 角度看是字串屬性值。 甚至連其他基本型別 (例如 Double) 一開始都是 XAML 處理器的字串。
在大部分的情況下,XAML 處理器需要有兩項資訊,才能處理屬性值。 第一項資訊是所要設定之屬性的實值型別。 定義屬性值且以 XAML 處理的任何字串最終都必須轉換或解析成該型別的值。 如果該值是 XAML 剖析器理解的基本型別,則會嘗試直接轉換字串。 如果屬性的值參考列舉,則會對提供的字串檢查是否有與該列舉中的具名常數相符的名稱。 而如果值不是剖析器理解的基本型別,也不是列舉中的常數名稱,則適用型別必須能夠提供以轉換後的字串為基礎的值或參考。
![]() |
---|
XAML 語言指示詞不會使用型別轉換子。 |
型別轉換子和標記延伸
標記延伸用法在檢查屬性型別和其他考量因素之前,必須由 XAML 處理器進行處理。 例如,如果設為屬性 (Attribute) 的屬性 (Property) 通常具有型別轉換,但在特定情況下此屬性 (Property) 由標記延伸用法進行設定,則標記延伸行為會優先處理。 需要使用標記延伸的其中一種常見的情況是建立已經存在之物件的參考。 在此情況下,無狀態的型別轉換子只能產生可能不需要用到的新執行個體。 如需標記延伸的詳細資訊,請參閱 XAML 標記延伸概觀。
原生型別轉換子
在 WPF 和 .NET XAML 服務實作中,特定 CLR 型別會有原生型別轉換處理,但是,這些 CLR 型別不是習慣上視為基本型別的型別。 這類型別的範例為 DateTime。 這種情況的原因之一是 .NET Framework 架構的運作方式:型別 DateTime 是在 mscorlib 中定義,但大部分基本程式庫是在 .NET 中定義。 DateTime 不允許以來自引入相依性 (TypeConverterAttribute 來自 System) 的另一個組件之屬性設為其屬性,因此不支援透過設定屬性的常用型別轉換探索機制。 XAML 剖析器擁有需要原生處理的型別清單,並且會以類似於真正處理基本型別的方式處理這些型別。 就 DateTime 而言,在進行這項處理時,將會呼叫 Parse。
實作型別轉換子
以下幾節將討論 TypeConverter 類別的 API。
TypeConverter
在 .NET Framework XAML 服務之下,用於 XAML 的所有型別轉換子都是衍生自基底類別 TypeConverter 的類別。 TypeConverter 類別存在於比 XAML 更早的 .NET Framework 版本中;其中一種原始 TypeConverter 情節是為視覺化設計工具中的屬性編輯器提供字串轉換。
在 XAML 中,TypeConverter 的角色有所擴充。 使用於 XAML 時,TypeConverter 會做為替特定的目標字串與來源字串轉換提供支援的基底類別。 來源字串可讓您剖析來自 XAML 的字串屬性值。 目標字串則可用以將特定物件屬性的執行階段值重新處理為 XAML 中的屬性,以進行序列化。
TypeConverter 會定義四個與目標字串和來源字串的轉換有關的成員,以供 XAML 處理之用:
在這些成員中,最重要的方法是 ConvertFrom,它可將輸入字串轉換成必要的物件型別。 ConvertFrom 方法經實作後,可將範圍較大的型別轉換成預定目地型別的轉換子。 因此,此方法可用於 XAML 以外的用途,例如支援執行階段轉換。 但在用於 XAML 時,只有可處理 String 輸入的程式碼路徑具有重要性。
第二重要的方法是 ConvertTo。 如果應用程式已轉換成標記表示 (例如,儲存至 XAML 做為檔案),則 ConvertTo 會用於 XAML 文字寫入器的較大案例中,以產生標記表示。 在此情況下,XAML 的重要程式碼路徑是在呼叫者傳遞 String 型別的 destinationType 時。
CanConvertTo 和 CanConvertFrom 則是在服務查詢 TypeConverter 實作的功能時所使用的支援方法。 您必須實作這些方法,針對轉換子的對等轉換方法支援的特定型別案例傳回 true。 針對 XAML 的目的,通常這是指 String 型別。
XAML 的文化特性資訊和型別轉換子
每個 TypeConverter 實作對於何者為轉換的有效字串都可以有各自的解譯,而且也可以使用或忽略當做參數傳遞的型別描述。 文化特性與 XAML 型別轉換的重要考量如下:雖然 XAML 支援以當地語系化字串做為屬性值,但您無法使用這些可當地語系化的字串,做為具有特定文化特性需求的型別轉換子輸入。 之所以有這項限制,是因為 XAML 屬性值的型別轉換子涉及會使用 en-US 文化特性的必然固定語言 XAML 處理行為。 如需設計此限制之原因的詳細資訊,請參閱 XAML 語言規格 ([MS-XAML]) 或 WPF 全球化和當地語系化概觀。
文化特性可能會造成問題的情況,包括某些文化特性會使用逗號 (而非句號) 做為字串格式數字的小數點分隔符號。 這種使用方式會與許多現有型別轉換子的行為發生衝突,因為後者使用逗號做為分隔符號。 透過 xml:lang 在週邊 XAML 中傳遞文化特性,並無法解決此問題。
實作 ConvertFrom
為了要當做支援 XAML 的 TypeConverter 實作使用,該轉換子的 ConvertFrom 方法必須接受以字串做為 value 參數。 如果字串的格式有效,而且可以透過 TypeConverter 實作進行轉換,則傳回的物件必須支援轉型為屬性所預期的型別。 否則,ConvertFrom 實作就必須傳回 null。
每個 TypeConverter 實作對於何者為轉換的有效字串都可以有各自的解譯,而且也可以使用或忽略當做參數傳遞的型別描述或文化特性內容。 不過,在 WPF 中的 XAML 語句處理可能不會在所有情況中都傳遞值給型別描述內容,也可能不會根據 xml:lang 傳遞文化特性。
![]() |
---|
請勿使用大括弧 ({}) 做為字串格式的項目,尤其是左大括號 ({)。這些字元是進入及結束標記延伸序列的保留字元。 |
如果您的型別轉換子必須能夠從 .NET Framework XAML 服務物件寫入器存取 XAML 服務,但是在內容下呼叫的 GetService 並未傳回該服務,則應擲回例外狀況。
實作 ConvertTo
ConvertTo 可能用於序列化支援。 透過自訂型別及其型別轉換子之 ConvertTo 的序列化支援並不是絕對必要的一項需求。 不過,如果您要實作控制項,或是使用序列化做為類別功能或設計的一部分,則應該實作 ConvertTo。
為了要當做支援 XAML 的 TypeConverter 實作使用,該轉換子的 ConvertTo 方法必須接受支援型別的執行個體 (或值) 做為 value 參數。 若 destinationType 參數的型別是 String,則傳回的物件必須能夠轉型為 String。 傳回的字串必須代表 value 的序列化值。 理想狀況下,您選擇的序列化格式所產生的值,應等同於該字串已傳遞至同一個轉換子的 ConvertFrom 實作時所產生的值,而不會嚴重流失資訊。
如果值無法序列化,或是轉換子不支援序列化,ConvertTo 實作必須傳回 null,而且可以擲回例外狀況。 但如果您確實擲回例外狀況,則應回報無法使用該轉換做為 CanConvertTo 實作一部分的情況,如此才能支援先檢查 CanConvertTo 以避免例外狀況的最佳作法。
如果 destinationType 參數的型別不是 String,您可以選擇自己的轉換子處理。 通常您會還原成基底實作處理,以便在基底 ConvertTo 中引發特定例外狀況。
如果您的型別轉換子必須能夠從 .NET Framework XAML 服務物件寫入器存取 XAML 服務,但是在內容下呼叫的 GetService 並未傳回該服務,則應擲回例外狀況。
實作 CanConvertFrom
您的 CanConvertFrom 實作應該針對型別 String 的 sourceType 傳回 true,否則便會交由基底實作處理。 請勿從 CanConvertFrom 擲回例外狀況。
實作 CanConvertTo
您的 CanConvertTo 實作應該針對型別 String 的 destinationType 傳回 true,否則便會交由基底實作處理。 請勿從 CanConvertTo 擲回例外狀況。
套用 TypeConverterAttribute
若要讓 .NET Framework XAML 服務將自訂型別轉換子當做自訂類別的現用型別轉換子,您必須將 .NET Framework attribute TypeConverterAttribute 套用至您的類別定義。 您透過屬性 (Attribute) 指定的 ConverterTypeName 必須是自訂型別轉換子的型別名稱。 如果您套用此屬性 (Attribute),當 XAML 處理器處理值時,若屬性 (Property) 型別使用您的自訂類別型別,該處理器便可輸入字串並傳回物件執行個體。
您也可以針對個別的屬性提供型別轉換子。 請將 .NET Framework attribute TypeConverterAttribute 套用到屬性 (Property) 定義 (主要定義,不是主要定義內的 get/set 實作),而不要套用到類別定義。 屬性的型別必須符合自訂型別轉換子所處理的型別。 套用此屬性 (Attribute) 之後,XAML 處理器就可以在處理該屬性 (Property) 的值時,處理輸入字串並傳回物件執行個體。 如果您選擇使用來自 Microsoft .NET Framework 或其他程式庫的屬性型別,而無法控制類別定義,也無法套用 TypeConverterAttribute,則根據個別屬性提供型別轉換子的方法特別有用。
若要為自訂附加成員提供型別轉換行為,請將 TypeConverterAttribute 套用至該附加成員之實作模式的 Get 存取子方法。
從標記延伸實作存取服務提供者內容
所有值轉換子可用的服務都相同。 差別在於每個值轉換子接收服務內容的方式。 服務存取方式和可用服務的相關說明,列載於 XAML 的型別轉換子和標記延伸主題中。
XAML 節點資料流中的型別轉換子
您在使用 XAML 節點資料流時,型別轉換子的動作或最終結果尚未執行。 在載入路徑中,最終需要進行型別轉換才能載入的屬性字串,仍是開始成員與結束成員內的文字值。 最終需要用於此作業的型別轉換子,可透過 XamlMember.TypeConverter 屬性來判定。 但若要從 XamlMember.TypeConverter 取得有效值,必須具有 XAML 結構描述內容;此內容可透過基礎成員或該成員所使用的物件值型別,來存取此類資訊。 若要叫用型別轉換行為,必須進行型別對應及建立轉換子執行個體,因此必須有 XAML 結構描述內容。