定義自定義類型以搭配 .NET XAML 服務使用
當您定義屬於商務物件的自定義類型,或是不相依於特定架構的類型時,您可以遵循某些 XAML 最佳做法。 如果您遵循這些作法,.NET XAML 服務及其 XAML 讀取器和 XAML 寫入器可以探索您類型的 XAML 特性,並使用 XAML 類型系統在 XAML 節點數據流中提供適當的表示法。 本主題描述類型定義、成員定義和CLR的最佳做法,這些類型或成員的關聯性。
XAML 的建構函式模式和類型定義
若要在 XAML 中具現化為物件專案,自訂類別必須符合下列需求:
自定義類別必須是公用的,而且必須公開無參數的公用建構函式。 (如需有關結構的注意事項,請參閱下一節。
自定義類別不得為巢狀類別。 全名路徑中的額外「點」會使類別命名空間除法模棱兩可,並干擾其他 XAML 功能,例如附加屬性。 如果物件可以具現化為物件專案,則建立的物件可以填滿任何將對象視為其基礎類型之屬性的屬性專案形式。
如果您啟用值轉換器,您仍然可以為不符合這些準則的類型提供物件值。 如需詳細資訊,請參閱 XAML的型別轉換子和標記延伸。
結構
結構一律能夠透過 CLR 定義在 XAML 中建構。 這是因為 CLR 編譯程式會隱含地建立結構的無參數建構函式。 這個建構函式會將所有屬性值初始化為預設值。
在某些情況下,不需要結構的預設建構行為。 這可能是因為 結構的目的是要以聯集的形式填滿值和函式。 作為等位,自主值可能會有互斥的解譯,因此,其屬性都無法設定。 WPF 詞彙中這類結構的範例是 GridLength。 這類結構應該實作型別轉換子,以便以屬性形式表示值,方法是使用建立結構值的不同解譯或模式的字串慣例。 結構也應該透過非無參數建構函式公開程式代碼建構的類似行為。
介面
介面可以做為成員的基礎類型。 XAML 類型系統會檢查可指派的清單,並預期提供做為值的物件可以指派給 介面。 只要相關的可指派類型支援 XAML 建構需求,介面必須如何呈現為 XAML 類型的概念。
Factory 方法
Factory 方法是 XAML 2009 功能。 他們會修改對象必須具有無參數建構函式的 XAML 準則。 本文未記載處理站方法。 請參閱 x:FactoryMethod 指示詞。
枚舉
列舉具有 XAML 原生類型轉換行為。 XAML 中指定的列舉常數名稱會根據基礎列舉類型解析,並將列舉值傳回 XAML 物件寫入器。
XAML 支援具有套用 FlagsAttribute 之列舉的旗標樣式用法。 如需詳細資訊,請參閱 XAML 語法詳細。 (XAML 語法詳細 是針對 WPF 物件所撰寫,但該主題中的大部分資訊都與不是特定實作架構特定的 XAML 相關。
成員定義
類型可以定義 XAML 使用方式的成員。 類型可以定義可使用 XAML 的成員,即使該特定類型不可使用 XAML 也一樣。 這是可能的,因為CLR繼承。 只要繼承成員的某些類型支援 XAML 使用方式做為類型,而且該成員支援其基礎類型的 XAML 使用方式,或具有可用的原生 XAML 語法,該成員即為 XAML 使用。
性能
如果您使用 CLR get
與 set
存取子模式和語言適當的關鍵字,將屬性定義為公用 CLR 屬性,則 XAML 類型系統可以將屬性報告為成員,並提供 XamlMember 屬性的適當資訊,例如 IsReadPublic 和 IsWritePublic。
特定屬性可以套用 TypeConverterAttribute來啟用文字語法。 如需詳細資訊,請參閱 XAML的型別轉換子和標記延伸。
如果沒有文字語法或原生 XAML 轉換,而且沒有進一步間接存取,例如標記延伸使用方式,屬性的類型(在 XAML 類型系統中TargetType)必須能夠藉由將目標類型視為 CLR 類型,將實例傳回 XAML 物件寫入器。
如果使用 XAML 2009,x:Reference Markup Extension 可用來提供不符合先前考慮的值;不過,這比類型定義問題更多的是使用問題。
事件
如果您將事件定義為公用CLR事件,XAML 類型系統可以將事件報告為成員,IsEvent 為 true
。 連接事件處理程式不在 .NET XAML 服務功能的範圍內;線路會留給特定的架構和實作。
方法
方法的內嵌程式代碼不是預設的 XAML 功能。 在大部分情況下,您不會直接從 XAML 參考方法成員,而且 XAML 中方法的角色只會提供特定 XAML 模式的支援。 x:FactoryMethod 指示詞 是例外狀況。
領域
CLR 設計指導方針禁止非靜態字段。 針對靜態欄位,您只能透過 x:Static Markup Extension
可附加的成員
可附加成員會透過定義型別上的存取子方法模式向 XAML 公開。 定義型別本身不需要做為物件可以使用 XAML。 事實上,常見的模式是宣告服務類別,其角色是擁有可附加成員並實作相關行為,但不會提供其他函式,例如UI表示法。 針對下列各節,佔位元 PropertyName 代表可附加成員的名稱。 該名稱必須在 XamlName 文法中有效。
請謹慎注意這些模式與類型的其他方法之間的名稱衝突。 如果成員存在符合其中一個模式的成員,即使不是您的意圖,也可以由 XAML 處理器將其解譯為可附加成員使用路徑。
GetPropertyName 存取子
GetPropertyName
存取子的簽章必須是:
public static object GetPropertyName(object target)
target
物件可以在實作中指定為更特定的類型。 您可以使用此選項來限定可附加成員的使用範圍;在預定範圍以外的用法會擲回無效的轉換例外狀況,然後由 XAML 剖析錯誤呈現。 參數名稱target
並非必要專案,而是在大部分實作中依慣例命名為target
。傳回值可以在實作中指定為更特定的類型。
若要支援 TypeConverter 啟用附加成員屬性使用方式的文字語法,請將 TypeConverterAttribute 套用至 GetPropertyName
存取子。 套用至 get
,而不是 set
似乎非直覺式;不過,此慣例可支援可串行化只讀附加成員的概念,這在設計工具案例中很有用。
SetPropertyName 存取子
SetPropertyName
存取子的簽章必須是:
public static void SetPropertyName(object target, object value)
target
物件可以指定為實作中更特定的類型,其邏輯和後果與上一節所述相同。value
物件可以在實作中指定為更特定的類型。
請記住,這個方法的值是來自 XAML 使用方式的輸入,通常是屬性形式。 從屬性表單中,文字語法必須有值轉換器支援,而且您在 GetPropertyName
存取子上屬性。
可附加的成員存放區
存取子方法通常不足以提供將可附加成員值放入物件圖形的方法,或擷取物件圖形中的值,並正確地串行化它們。 若要提供這項功能,先前存取子簽章中的 target
對象必須能夠儲存值。 儲存機制應與可附加成員原則一致,該成員可附加至成員不在成員清單中的目標。 .NET XAML 服務透過 API IAttachedPropertyStore 和 AttachablePropertyServices提供可附加成員存放區的實作技術。 XAML 寫入器會使用 IAttachedPropertyStore 來探索存放區實作,而且應該在存取子 target
的類型上實作。 靜態 AttachablePropertyServices API 會在存取子主體內使用,並透過其 AttachableMemberIdentifier來參考可附加成員。
XAML-Related CLR 屬性
正確地將類型、成員和元件歸結為重要,以便向 .NET XAML 服務報告 XAML 類型系統資訊。 如果適用下列任一情況,則報告 XAML 類型系統資訊是相關的:
- 您打算將類型與直接以 .NET XAML 服務 XAML 讀取器和 XAML 寫入器為基礎的 XAML 系統搭配使用。
- 您可以定義或使用以這些 XAML 讀取器和 XAML 寫入器為基礎的 XAML 利用架構。
如需與自訂類型 XAML 支援相關的每個 XAML 相關屬性清單,請參閱 XAML-Related 自訂類型和連結庫的 CLR 屬性。
用法
使用自定義類型時,標記作者必須對應包含自定義類型的元件和CLR命名空間的前置詞。 本主題中未記載此程式。
存取層級
XAML 提供方法來載入和具現化具有 internal
存取層級的類型。 提供這項功能,讓使用者程式代碼可以定義自己的類型,然後從屬於相同使用者程式代碼範圍的標記具現化這些類別。
WPF 的範例是,每當使用者程式代碼定義 UserControl,該 UserControl 是重構 UI 行為的一種方式,但不是任何可能透過宣告支持類別與 public
存取層級所隱含的可能延伸機制的一部分。 如果備份程式代碼編譯成與 XAML 型別參考的相同元件,則可以使用 internal
存取宣告這類 UserControl。
對於在完全信任下載入 XAML 並使用 XamlObjectWriter的應用程式,一律會啟用載入具有 internal
存取層級的類別。
對於在部分信任下載入 XAML 的應用程式,您可以使用 XamlAccessLevel API 來控制存取層級特性。 此外,延遲機制(例如 WPF 範本系統)必須能夠傳播任何存取層級許可權,並保留它們以供最終運行時間評估使用;這會透過傳遞 XamlAccessLevel 資訊在內部處理。
WPF 實作
WPF XAML 會使用部分信任存取模型,其中如果BAML在部分信任下載入,則存取限制為BAML來源的元件 AssemblyAccessTo。 對於延遲,WPF 會使用 IXamlObjectWriterFactory.GetParentSettings 作為傳遞存取層級信息的機制。
在 WPF XAML 術語中,內部類型 是由同時包含參考 XAML 的相同元件所定義的類型。 這類類型可以透過刻意省略對應元件= 部分的 XAML 命名空間進行對應,例如,xmlns:local="clr-namespace:WPFApplication1"
。 如果BAML參考內部類型,且該類型具有 internal
存取層級,這會產生元件的 GeneratedInternalTypeHelper
類別。 如果您想要避免 GeneratedInternalTypeHelper
,您必須使用 public
存取層級,或必須將相關類別納入個別元件,並使該元件相依。