標記延伸和 WPF XAMLMarkup Extensions and WPF XAML

本主題介紹 XAML 標記延伸模組概念,包括其語法規則、用途,以及其根據的類別物件模型。This topic introduces the concept of markup extensions for XAML, including their syntax rules, purpose, and the class object model that underlies them. 標記延伸模組是 XAML 語言的一般功能,以及 XAML 服務之 .NET 實作的一般功能。Markup extensions are a general feature of the XAML language and of the .NET implementation of XAML services. 本主題會具體詳述 WPF XAML 中所使用的標記延伸模組。This topic specifically details markup extensions for use in WPF XAML.

XAML 處理器和標記延伸模組XAML Processors and Markup Extensions

一般而言,XAML 剖析器可以將屬性值解譯為可轉換成基本項目的常值字串,或透過一些方法將它轉換成物件。Generally speaking, a XAML parser can either interpret an attribute value as a literal string that can be converted to a primitive, or convert it to an object by some means. 其中一種這類方式是透過參考類型轉換子;這記錄於 TypeConverters 和 XAML 主題。One such means is by referencing a type converter; this is documented in the topic TypeConverters and XAML. 不過,有些情況需要不同的行為。However, there are scenarios where different behavior is required. 例如,可以向 XAML 處理器指示,屬性的值不應該導致物件圖形中的新物件。For example, a XAML processor can be instructed that a value of an attribute should not result in a new object in the object graph. 相反地,此屬性應該會產生參考圖形另一個組件中的已建構物件或靜態物件的物件圖表。Instead, the attribute should result in an object graph that makes a reference to an already constructed object in another part of the graph, or a static object. 另一個情況是可以指示 XAML 處理器使用將非預設引數提供給物件建構函式的語法。Another scenario is that a XAML processor can be instructed to use a syntax that provides non-default arguments to the constructor of an object. 這些是標記延伸模組可提供解決方案的案例類型。These are the types of scenarios where a markup extension can provide the solution.

基本標記延伸模組語法Basic Markup Extension Syntax

可以實作標記延伸模組,以提供屬性 (attribute) 用法中的屬性 (property) 值、屬性 (property) 項目用法中的屬性 (property),或兩者。A markup extension can be implemented to provide values for properties in an attribute usage, properties in a property element usage, or both.

用來提供屬性值時,可區分 XAML 處理器之標記延伸模組序列的語法是存在左右大括號 ({ 和 })。When used to provide an attribute value, the syntax that distinguishes a markup extension sequence to a XAML processor is the presence of the opening and closing curly braces ({ and }). 標記延伸模組的類型則是透過緊接在左大括號後面的字串語彙基元所識別。The type of markup extension is then identified by the string token immediately following the opening curly brace.

在屬性項目語法中使用時,標記延伸模組在視覺上與任何其他用來提供屬性項目值的項目相同︰將標記延伸模組類別參考為以角括弧括住 (<>) 之項目的 XAML 項目宣告。When used in property element syntax, a markup extension is visually the same as any other element used to provide a property element value: a XAML element declaration that references the markup extension class as an element, enclosed within angle brackets (<>).

已定義 XAML 的標記延伸XAML-Defined Markup Extensions

數個標記延伸模組不是 XAML 的 WPF 實作所特有,而是作為語言之 XAML 的內建功能或功能實作。Several markup extensions exist that are not specific to the WPF implementation of XAML, but are instead implementations of intrinsics or features of XAML as a language. 這些標記延伸模組在 System.Xaml 組件中實作為一般 .NET Framework XAML 服務的一部分,並且位在 XAML 語言 XAML 命名空間內。These markup extensions are implemented in the System.Xaml assembly as part of the general .NET Framework XAML services, and are within the XAML language XAML namespace. 根據常見標記用法,這些標記延伸模組通常可以透過用法中的 x: 前置詞進行識別。In terms of common markup usage, these markup extensions are typically identifiable by the x: prefix in the usage. MarkupExtension基類 (也定義于 system.string) 提供了所有標記延伸應使用的模式, 以便在 xaml 讀取器和 xaml 寫入器中支援, 包括 WPF Xaml。The MarkupExtension base class (also defined in System.Xaml) provides the pattern that all markup extensions should use in order to be supported in XAML readers and XAML writers, including in WPF XAML.

  • x:Type 提供具名類型的 Type 物件。x:Type supplies the Type object for the named type. 這項工具最常用於樣式和範本。This facility is used most frequently in styles and templates. 如需詳細資訊,請參閱 x:Type 標記延伸模組For details, see x:Type Markup Extension.

  • x:Static 會產生靜態值。x:Static produces static values. 值來自實值類型程式碼實體,而此實體不是直接為目標屬性值類型,但可以評估為該類型。The values come from value-type code entities that are not directly the type of a target property's value, but can be evaluated to that type. 如需詳細資訊,請參閱 x:Static 標記延伸模組For details, see x:Static Markup Extension.

  • x:Null 指定 null 作為屬性的值,而且可以用於屬性 (attribute) 或屬性 (property) 項目值。x:Null specifies null as a value for a property and can be used either for attributes or property element values. 如需詳細資訊,請參閱 x:Null 標記延伸模組For details, see x:Null Markup Extension.

  • 如果故意不使用 WPF 基底項目和控制項模型所提供的集合支援,則 x:Array 支援使用 XAML 語法來建立一般陣列。x:Array provides support for creation of general arrays in XAML syntax, for cases where the collection support provided by WPF base elements and control models is deliberately not used. 如需詳細資訊,請參閱 x:Array 標記延伸模組For details, see x:Array Markup Extension.

注意

x: 前置詞用於 XAML 檔案或生產的根項目中 XAML 語言內建功能的一般 XAML 命名空間對應。The x: prefix is used for the typical XAML namespace mapping of the XAML language intrinsics, in the root element of a XAML file or production. 例如, WPF 應用程式的 Visual Studio 範本會使用此x:對應來起始 XAML 檔案。For example, the Visual Studio templates for WPF applications initiate a XAML file using this x: mapping. 您可以選擇專屬 XAML 命名空間對應中的不同前置詞語彙基元,但是這份文件將假設使用預設 x: 對應來識別這些是 XAML 語言 XAML 命名空間之已定義部分的實體,而非與特定架構無關的 WPF 預設命名空間或其他 XML 命名空間。You could choose a different prefix token in your own XAML namespace mapping, but this documentation will assume the default x: mapping as a means of identifying those entities that are a defined part of the XAML namespace for the XAML language, as opposed to the WPF default namespace or other XAML namespaces not related to a specific framework.

WPF 特定標記延伸模組WPF-Specific Markup Extensions

WPF 程式設計中所使用的最常見標記延伸模組是支援資源參考的標記延伸模組 (StaticResourceDynamicResource),以及支援資料繫結的標記延伸模組 (Binding)。The most common markup extensions used in WPF programming are those that support resource references (StaticResource and DynamicResource), and those that support data binding (Binding).

  • StaticResource 會替代已定義資源的值,來提供屬性的值。StaticResource provides a value for a property by substituting the value of an already defined resource. StaticResource 評估最終會在 XAML 載入期間進行,而且無法在執行階段存取物件圖形。A StaticResource evaluation is ultimately made at XAML load time and does not have access to the object graph at run time. 如需詳細資訊,請參閱 StaticResource 標記延伸模組For details, see StaticResource Markup Extension.

  • DynamicResource 會針對屬性提供一個值,方式是延後該值,使其變成資源的執行階段參考。DynamicResource provides a value for a property by deferring that value to be a run-time reference to a resource. 動態資源參考可在每次存取這類資源時強制執行新的查閱作業,而且可以在執行階段存取物件圖形。A dynamic resource reference forces a new lookup each time that such a resource is accessed and has access to the object graph at run time. 若要取得這項存取,WPF 屬性系統中的相依性屬性以及評估過的運算式都支援 DynamicResource 概念。In order to get this access, DynamicResource concept is supported by dependency properties in the WPF property system, and evaluated expressions. 因此,您只能針對相依性屬性目標使用 DynamicResourceTherefore you can only use DynamicResource for a dependency property target. 如需詳細資訊,請參閱 DynamicResource 標記延伸模組For details, see DynamicResource Markup Extension.

  • Binding 使用在執行階段套用至父物件的資料內容,來提供屬性的資料繫結值。Binding provides a data bound value for a property, using the data context that applies to the parent object at run time. 此標記延伸模組啟用用於指定資料繫結的重大內嵌語法,因此相當複雜。This markup extension is relatively complex, because it enables a substantial inline syntax for specifying a data binding. 如需詳細資訊,請參閱Binding 標記延伸模組For details, see Binding Markup Extension.

  • RelativeSource提供的來源資訊Binding , 可以在執行時間物件樹狀結構中流覽數個可能的關聯性。RelativeSource provides source information for a Binding that can navigate several possible relationships in the run-time object tree. 這會提供在多用途範本中所建立或使用程式碼所建立之繫結的特殊化來源,而不需要完全了解周圍物件樹狀結構。This provides specialized sourcing for bindings that are created in multi-use templates or created in code without full knowledge of the surrounding object tree. 如需詳細資訊,請參閱 RelativeSource 標記延伸模組For details, see RelativeSource MarkupExtension.

  • TemplateBinding 可讓控制項範本使用範本屬性的值,而範本屬性來自將使用範本之類別的物件模型定義屬性。TemplateBinding enables a control template to use values for templated properties that come from object-model-defined properties of the class that will use the template. 換句話說,範本定義內的屬性可以存取只在套用範本後存在的內容。In other words, the property within the template definition can access a context that only exists once the template is applied. 如需詳細資訊,請參閱 TemplateBinding 標記延伸模組For details, see TemplateBinding Markup Extension. 如需 TemplateBinding 實際使用的詳細資訊,請參閱 Styling with ControlTemplates Sample (使用 ControlTemplates 設定樣式範例)。For more information on the practical use of TemplateBinding, see Styling with ControlTemplates Sample.

  • ColorConvertedBitmap 支援一個相當進階的影像處理案例。ColorConvertedBitmap supports a relatively advanced imaging scenario. 如需詳細資訊,請參閱 ColorConvertedBitmap 標記延伸模組For details, see ColorConvertedBitmap Markup Extension.

  • ComponentResourceKeyThemeDictionary 支援資源查閱各層面,特別是針對與自訂控制項一起封裝的資源和主題。ComponentResourceKey and ThemeDictionary support aspects of resource lookup, particularly for resources and themes that are packaged with custom controls. 如需詳細資訊,請參閱 ComponentResourceKey 標記延伸模組ThemeDictionary 標記延伸模組控制項撰寫概觀For more information, see ComponentResourceKey Markup Extension, ThemeDictionary Markup Extension, or Control Authoring Overview.

*延伸模組類別*Extension Classes

針對一般 XAML 語言和 WPF 特定的標記延伸, 每個標記延伸的行為都會透過*Extension衍生自MarkupExtension的類別識別為 XAML 處理器, 並提供ProvideValue方法.For both the general XAML language and WPF-specific markup extensions, the behavior of each markup extension is identified to a XAML processor through a *Extension class that derives from MarkupExtension, and provides an implementation of the ProvideValue method. 每個延伸模組上的這個方法提供在評估標記延伸模組時所傳回的物件。This method on each extension provides the object that is returned when the markup extension is evaluated. 所傳回的物件一般是根據傳遞至標記延伸模組的各種字串語彙基元所評估。The returned object is typically evaluated based on the various string tokens that are passed to the markup extension.

例如, StaticResourceExtension類別會提供實際資源查閱的介面執行, 讓其ProvideValue實值傳回要求的物件, 而該特定執行的輸入是用來執行的字串。依其x:Key查詢資源。For example, the StaticResourceExtension class provides the surface implementation of actual resource lookup so that its ProvideValue implementation returns the object that is requested, with the input of that particular implementation being a string that is used to look up the resource by its x:Key. 如果您要使用現有的標記延伸模組,則此實作詳細資料大部分不重要。Much of this implementation detail is unimportant if you are using an existing markup extension.

某些標記延伸模組未使用字串語彙基元引數。Some markup extensions do not use string token arguments. 這是因為它們會傳回靜態或一致值,或利用透過 serviceProvider 參數所傳遞的其中一個服務可以取得應該傳回值的內容。This is either because they return a static or consistent value, or because context for what value should be returned is available through one of the services passed through the serviceProvider parameter.

*Extension 命名模式是基於方便性和一致性。The *Extension naming pattern is for convenience and consistency. XAML 處理器將該類別識別為標記延伸模組支援,則不需要它。It is not necessary in order for a XAML processor to identify that class as support for a markup extension. 只要您的程式碼基底包含 system.string, 並使用 .NET Framework xaml 服務實作為, 就必須將它辨識為 xaml 標記延伸, 以衍生自MarkupExtension和以支援結構化語法。So long as your codebase includes System.Xaml and uses .NET Framework XAML Services implementations, all that is necessary to be recognized as a XAML markup extension is to derive from MarkupExtension and to support a construction syntax. WPF 會定義標記延伸模組, 並啟用不遵循*Extension命名模式的類別, Binding例如。WPF defines markup extension-enabling classes that do not follow the *Extension naming pattern, for example Binding. 通常這是因為此類別支援純標記延伸模組支援以外的案例。Typically the reason for this is that the class supports scenarios beyond pure markup extension support. 在案例Binding中, 該類別針對與 XAML 無關的案例, 支援對物件的方法和屬性進行執行時間存取。In the case of Binding, that class supports run-time access to methods and properties of the object for scenarios that have nothing to do with XAML.

初始化文字的延伸模組類別解譯Extension Class Interpretation of Initialization Text

XAML 處理器會使用下列其中一種方式來解譯位在標記延伸模組名稱後面而且仍在大括弧內的字串語彙基元:The string tokens following the markup extension name and still within the braces are interpreted by a XAML processor in one of the following ways:

  • 逗號一律會代表個別語彙基元的分隔符號。A comma always represents the separator or delimiter of individual tokens.

  • 如果個別分隔的語彙基元未包含任何等號,則會將每個語彙基元視為建構函式引數。If the individual separated tokens do not contain any equals signs, each token is treated as a constructor argument. 每個建構函式參數都必須指定為該簽章所預期的類型,並且為該簽章所預期的適當順序。Each constructor parameter must be given as the type expected by that signature, and in the proper order expected by that signature.

    注意

    XAML 處理器必須呼叫建構函式,以與配對數目的引數計數相符。A XAML processor must call the constructor that matches the argument count of the number of pairs. 基於這個理由, 如果您正在執行自訂標記延伸, 請不要提供具有相同引數計數的多個函式。For this reason, if you are implementing a custom markup extension, do not provide multiple constructors with the same argument count. 有多個具有相同參數計數的標記延伸模組建構函式路徑時,未定義 XAML 處理器運作方式的行為,但您應該預期在標記延伸模組類型定義發生此情況時,允許 XAML 處理器擲回用法例外狀況。The behavior for how a XAML processor behaves if more than one markup extension constructor path with the same parameter count exists is not defined, but you should anticipate that a XAML processor is permitted to throw an exception on usage if this situation exists in the markup extension type definitions.

  • 如果個別的分隔標記包含等號, 則 XAML 處理器會先呼叫標記延伸的無參數的函式。If the individual separated tokens contain equals signs, then a XAML processor first calls the parameterless constructor for the markup extension. 則每個「名稱=值」配對都會解譯為標記延伸模組上的屬性名稱,以及要指派給該屬性的值。Then, each name=value pair is interpreted as a property name that exists on the markup extension, and a value to assign to that property.

  • 如果建構函式行為與標記延伸模組中的屬性設定行為之間有平行結果,則所使用的行為就不重要。If there is a parallel result between the constructor behavior and the property setting behavior in a markup extension, it does not matter which behavior you use. 如果只因為可讓您的標記更具意圖,而且您較不可能意外轉置建構函式參數,則較常見用法是使用有多個可設定屬性之標記延伸模組的「屬性」=「值」It is more common usage to use the property=value pairs for markup extensions that have more than one settable property, if only because it makes your markup more intentional and you are less likely to accidentally transpose constructor parameters. (當您指定「屬性=值」配對時,這些屬性可能是任意順序)。另外,不保證標記延伸模組提供可設定所有其可設定屬性的建構函式參數。(When you specify property=value pairs, those properties may be in any order.) Also, there is no guarantee that a markup extension supplies a constructor parameter that sets every one of its settable properties. 例如, Binding是一個標記延伸, 其中包含許多可透過屬性=表單中的延伸模組來設定的Binding屬性, 但僅支援兩個函式: 無參數的函式, 以及一個這會設定初始路徑。For example, Binding is a markup extension, with many properties that are settable through the extension in property=value form, but Binding only supports two constructors: a parameterless constructor, and one that sets an initial path.

  • 必須逸出,才能將常值逗號傳遞給標記延伸模組。A literal comma cannot be passed to a markup extension without escapement.

逸出序列和標記延伸模組Escape Sequences and Markup Extensions

XAML 處理器中的屬性處理使用大括號作為標記延伸模組序列的指標。Attribute handling in a XAML processor uses the curly braces as indicators of a markup extension sequence. 此外,必要時,也可能產生常值大括號字元屬性值,方法是使用後接常值大括號的空大括號配對來輸入逸出序列。It is also possible to produce a literal curly brace character attribute value if necessary, by entering an escape sequence using an empty curly brace pair followed by the literal curly brace. 請參閱 {} Escape 序列標記延伸See {} Escape Sequence - Markup Extension.

XAML 用法中的巢狀標記延伸模組Nesting Markup Extensions in XAML Usage

支援巢狀多個標記延伸模組,並且會先更深入地評估每個標記延伸模組。Nesting of multiple markup extensions is supported, and each markup extension will be evaluated deepest first. 例如,請考慮下列用法:For example, consider the following usage:

<Setter Property="Background"  
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />  

在此用法中,會先評估 x:Static 陳述式,並傳回字串。In this usage, the x:Static statement is evaluated first and returns a string. 該字串接著會用作 DynamicResource 的引數。That string is then used as the argument for DynamicResource.

標記延伸模組和屬性項目語法Markup Extensions and Property Element Syntax

用作填入屬性項目值的物件項目時,無法從可在 XAML 中使用的一般類型支援物件項目來透過視覺方式區別標記延伸模組類別。When used as an object element that fills a property element value, a markup extension class is visually indistinguishable from a typical type-backed object element that can be used in XAML. 一般物件項目與標記延伸模組的實際差異,在於標記延伸模組會評估為類型值或延後為運算式。The practical difference between a typical object element and a markup extension is that the markup extension is either evaluated to a typed value or deferred as an expression. 因此,標記延伸模組之屬性值的任何可能類型錯誤的機制會不同,就像其他程式設計模型中處理晚期繫結屬性的方式一樣。Therefore the mechanisms for any possible type errors of property values for the markup extension will be different, similar to how a late-bound property is treated in other programming models. 將會針對剖析 XAML 時所設定的目標屬性,評估一般物件項目的類型是否相符。An ordinary object element will be evaluated for type match against the target property it is setting when the XAML is parsed.

用於物件項目語法以填入屬性項目時,大部分標記延伸模組內不會有內容或任何進一步屬性項目語法。Most markup extensions, when used in object element syntax to fill a property element, would not have content or any further property element syntax within. 因此,您可以關閉物件項目標記,且不提供任何子項目。Thus you would close the object element tag, and provide no child elements. 只要 XAML 處理器遇到任何物件項目時,就會呼叫該類別的建構函式,以具現化從剖析的項目所建立的物件。Whenever any object element is encountered by a XAML processor, the constructor for that class is called, which instantiates the object created from the parsed element. 標記延伸類別是不一樣的: 如果您想要在物件專案語法中使用標記延伸模組, 則必須提供無參數的函式。A markup extension class is no different: if you want your markup extension to be usable in object element syntax, you must provide a parameterless constructor. 某些現有標記延伸模組有至少一個必要屬性值,而且必須指定一個必要屬性值才能進行有效初始化。Some existing markup extensions have at least one required property value that must be specified for effective initialization. 如果是這樣,該屬性值一般會指定為物件項目上屬性 (property) 的屬性 (attribute)。If so, that property value is typically given as a property attribute on the object element. 在 XAML 命名空間 (x:) 中語言功能WPF XAML 延伸模組參考頁面, 將會注明具有必要屬性的標記延伸 (以及必要屬性的名稱)。In the XAML Namespace (x:) Language Features and WPF XAML Extensions reference pages, markup extensions that have required properties (and the names of required properties) will be noted. 參考頁面也會標註是否不允許特定標記延伸模組的物件項目語法或屬性語法。Reference pages will also note if either object element syntax or attribute syntax is disallowed for particular markup extensions. 值得注意的案例是 x:Array 標記延伸模組,這無法支援屬性語法,因為必須在標記內將該陣列的內容指定為內容。A notable case is x:Array Markup Extension, which cannot support attribute syntax because the contents of that array must be specified within the tagging as content. 陣列內容會當成一般物件處理;因此,沒有屬性的預設類型轉換子是可行的。The array contents are handled as general objects, therefore no default type converter for the attribute is feasible. 此外,x:Array 標記延伸模組需要 type 參數。Also, x:Array Markup Extension requires a type parameter.

另請參閱See also