TypeConverter 和 XAML

本主題介紹將字串的類型轉換當成一般 XAML 語言功能的目的。 在 .NET Framework 中,類別 TypeConverter 會做為 Managed 自訂類別實作的一部分,做為 XAML 屬性使用方式中的屬性值的實作的一部分。 如果您撰寫自訂類別,而且希望類別的實例可作為 XAML 可設定屬性值使用,您可能需要將 套用 TypeConverterAttribute 至類別、撰寫自訂 TypeConverter 類別或兩者。

類型轉換概念

XAML 和字串值

在 XAML 檔案中設定屬性值時,該值的初始類型是純文字的字串。 即使是其他基本類型,例如 Double 一開始都是 XAML 處理器的文字字串。

XAML 處理器需要兩項資訊才能處理屬性值。 第一項資訊是正在設定之屬性的實值類型。 任何定義屬性值並在 XAML 中處理的字串最後必須轉換或解析成該類型的值。 如果值是 XAML 剖析器可理解的基本類型 (例如數值),則會嘗試直接轉換字串。 如果值是一個列舉,則用來檢查名稱的字串會符合該列舉中的具名常數。 如果值不是剖析器所辨識的基本類型,也不是列舉,則上述類型必須能夠根據已轉換的字串提供類型的執行個體或值。 您可以藉由指定類型轉換器類別來完成此動作。 類型轉換子實際上是一個 Helper 類別,可用於提供另一個類別的值,這兩者均適用於 XAML 案例,可能也適用於利用 .NET 程式碼進行程式碼呼叫。

在 XAML 中使用現有的類型轉換行為

根據您對基礎 XAML 概念的熟悉程度而定,您可能已經在基本應用程式 XAML 中使用類型轉換行為而不自知。 例如,WPF 會定義接受 類型 Point 值的數百個屬性。 Point是一個值,描述二維座標空間中的座標,而且它實際上只有兩個重要的屬性: XY 。當您在 XAML 中指定一個點時,您會將它指定為字串,其中包含您提供的 和 Y 值之間的 X 分隔符號(通常是逗號)。 例如: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>

即使是這個簡單型別 Point ,在 XAML 中的簡單用法也牽涉到型別轉換器。 在此情況下,即 類別 PointConverter

在類別層級定義的型別轉換器 Point 可簡化採用 Point 之所有屬性的標記使用方式。 若未在此處使用類型轉換器,您就需要針對先前所示的同一個範例使用下列更多較為詳細的標記:

<LinearGradientBrush>
  <LinearGradientBrush.StartPoint>
    <Point X="0" Y="0"/>
  </LinearGradientBrush.StartPoint>
  <LinearGradientBrush.EndPoint>
    <Point X="1" Y="1"/>
  </LinearGradientBrush.EndPoint>
</LinearGradientBrush>

是否要使用類型轉換字串或較為詳細的對等語法,通常是編碼樣式的選擇。 您的 XAML 工具工作流程可能也會影響值的設定方式。 一些 XAML 工具傾向於發出最詳細格式的標記,因為較容易反覆存取設計工具檢視或它自己的序列化機制。

在 WPF 和 .NET Framework 類型上通常可以探索現有的類型轉換器,方法是檢查類別 (或 屬性) 是否存在已套用 TypeConverterAttribute 。 這個屬性將基於 XAML 用途以及其他可能的用途,針對該類型的值,為支援類型轉換器的類別命名。

類型轉換器和標記延伸

標記延伸和類型轉換器會根據 XAML 處理器行為和套用它們的案例來填滿正交角色。 儘管有適合標記延伸使用的內容,但標記延伸負責提供值的屬性類型轉換行為在標記延伸實作中通常不會遭到檢查。 換句話說,即使標記延伸傳回文字字串做為其 ProvideValue 輸出,也不會在該字串上叫用套用至特定屬性或屬性值類型的類型轉換行為。一般來說,標記延伸的目的是在未涉及任何類型轉換器的情況下,處理字串並傳回物件。

需要標記延伸而不是類型轉換器的一個常見情況是參考現有的物件。 無狀態類型轉換器充其量只能產生新的執行個體,但這可能不是令人滿意的情況。 如需標記延伸的詳細資訊,請參閱標記延伸和 WPF XAML

原生類型轉換器

在 XAML 剖析器中的 WPF 和 .NET Framework 實作中,有些特定類型具有原生類型轉換處理,但卻不是依慣例會被視為基本類型的類型。 這類類型的範例是 DateTime。 這是因為 .NET Framework 架構的運作方式:類型 DateTime 是在 mscorlib 中定義,這是 .NET 中最基本的程式庫。 DateTime 不允許使用來自另一個引進相依性之元件的屬性來設定屬性, TypeConverterAttribute 因此無法支援依存機制的一般類型轉換器探索機制。 而是 XAML 剖析器會有一份需要這類原生處理的類型清單,這些類型的處理方式會與真正基本類型的處理方式類似 (在這種情況下 DateTime ,涉及對 Parse 的呼叫。

實作類型轉換器

TypeConverter

在先前提供的範例中 Point ,已提及 類別 PointConverter 。 針對 XAML 的 .NET 實作,所有用於 XAML 用途的類型轉換器都是衍生自基類 的類別 TypeConverter 。 類別 TypeConverter 存在於 XAML 存在之前的 .NET Framework 版本中;其原始用法之一是在視覺化設計工具中提供屬性對話方塊的字串轉換。 針對 XAML,的角色 TypeConverter 會展開為 的基類,以包含做為字串的基類,以及啟用剖析字串屬性值的字串轉換,並可能將特定物件屬性的運行時間值處理回字串,以序列化為屬性。

TypeConverter 定義四個成員,這些成員與用於 XAML 處理之字串的轉換和轉換相關:

其中最重要的方法是 ConvertFrom 。 這個方法會將輸入字串轉換為所需的物件類型。 嚴格來說, ConvertFrom 可以實作 方法,將更廣泛的型別轉換成轉換子的預期目的地類型,因此會提供超越 XAML 的目的,例如支援執行時間轉換,但基於 XAML 目的,它只是程式碼路徑可以處理 String 重要的輸入。

下一個最重要的方法是 ConvertTo 。 如果應用程式轉換成標記標記法(例如,如果它儲存至 XAML 做為檔案), ConvertTo 則負責產生標記標記法。 在此情況下,XAML 很重要的程式碼路徑是當您傳遞 destinationTypeString 時。

CanConvertToCanConvertFrom 是服務查詢 TypeConverter 實作之功能時所使用的支援方法。 您必須實作這些方法來傳回轉換器對等轉換方法所支援類型特有案例的 true。 基於 XAML,這通常表示 String 類型。

XAML 的文化特性資訊和類型轉換器

每個 TypeConverter 實作都可以自行解譯構成有效字串以進行轉換,也可以使用或忽略傳遞為參數的類型描述。 有一個關於文化特性和 XAML 類型轉換的重要考量。 XAML 完全支援使用可當地語系化的字串做為屬性值。 但不支援使用那個可當地語系化的字串做為具有特定文化特性需求的類型轉換器輸入,因為 XAML 屬性值的類型轉換器會使用 en-US 文化特性,來包含必然的固定語言剖析行為。 如需這項限制之設計原因的詳細資訊,您應該參閱 XAML 語言規格 ( [MS-XAML]

在文化特性可能是問題的範例中,某些文化特性會使用逗號做為數字的小數點分隔符號。 這將與許多 WPF XAML 類型轉換器所具備的行為相衝突,該行為是使用逗號做為分隔符號 (根據歷程的前置參照,例如,常見的 X,Y 格式或逗號分隔清單)。 即使是在局部的 XAML 中傳遞文化特性 (將 Languagexml:lang 設為 sl-SI 文化特性,以這種方式使用逗號代表小數點的文化特性範例),還是無法解決問題。

實作 ConvertFrom

若要可做為支援 XAML 的 TypeConverter 實作來重複使用,該轉換器的 ConvertFrom 方法必須接受字串做為 value 參數。 如果字串的格式有效,而且可由實作轉換 TypeConverter ,則傳回的物件必須支援轉換成 屬性所預期的型別。 否則, ConvertFrom 實作必須傳回 null

每個 TypeConverter 實作都可以自行解譯哪些內容構成有效的轉換字串,也可以使用或忽略傳遞為參數的類型描述或文化特性內容。 不過,WPF XAML 處理可能不會在所有情況下都將值傳遞至類型描述內容,也可能不會根據 xml:lang 來傳遞文化特性。

注意

請勿使用大括號字元 (特別是 {)做為字串格式的可能元素。 這些字元保留做為標記延伸序列的進入及結束。

實作 ConvertTo

ConvertTo 可能用於序列化支援。 透過自訂類型和其類型轉換器之 ConvertTo 的序列化支援不是絕對需求。 不過,如果您正在實作控制項,或使用功能某部分的序列化或類別設計,則應該實作 ConvertTo

若要當做 TypeConverter 支援 XAML 的實作使用, ConvertTo 該轉換子的 方法必須接受支援做為 value 參數的類型實例(或值)。 destinationType當 參數是 型別 String 時,傳回的物件必須能夠轉換成 String 。 傳回的字串必須代表 value 的序列化值。 在理想情況下,如果您選擇的序列化格式應該能夠在該字串傳遞至 ConvertFrom 相同轉換器的實作時產生相同的值,而不會大幅遺失資訊。

如果無法序列化值,或轉換子不支援序列化,則實 ConvertTo 作必須傳回 null ,而且在此情況下允許擲回例外狀況。 但是,如果您擲回例外狀況,您應該報告無法使用該轉換做為實 CanConvertTo 作的一部分,以便先檢查 CanConvertTo 最佳做法,以避免例外狀況受到支援。

如果 destinationType 參數不是 類型 String ,您可以選擇自己的轉換器處理。 一般而言,您會還原為基底實作處理,而基底 ConvertTo 會引發特定的例外狀況。

實作 CanConvertTo

您的 CanConvertTo 實作應該傳回類型 truedestinationTypeString,否則會進行基底實作。

實作 CanConvertFrom

您的 CanConvertFrom 實作應該傳回類型 truesourceTypeString,否則會進行基底實作。

套用 TypeConverterAttribute

若要讓自訂類型轉換器成為 XAML 處理器自訂類別的代理類型轉換器,您必須將 套用 TypeConverterAttribute 至類別定義。 您透過屬性指定的 ConverterTypeName 必須是您自訂類型轉換器的類型名稱。 如果已套用這個屬性,當 XAML 處理器處理屬性類型使用您自訂類別類型的值時,就可以輸入字串並傳回物件執行個體。

您也可以提供每個屬性的類型轉換器。 將 TypeConverterAttribute 套用至屬性定義 (主要定義,非其內的 get/set 實作),而不是將它套用至類別定義。 屬性的類型必須符合您自訂類型轉換器所處理的類型。 如果已套用這個屬性,則在 XAML 處理器處理該屬性的值時,可以處理輸入字串,並傳回物件執行個體。 如果您選擇從 Microsoft .NET Framework 使用屬性類型,或是無法控制類別定義且無法套用 TypeConverterAttribute 到該處的其他程式庫,則個別屬性類型轉換器技術特別有用。

另請參閱