Share via


XAML 語法詳細資料

本主題定義用於描述 XAML 語法項目的詞彙。 這些詞彙經常用於本文件的其他地方,尤其是 WPF 文件以及其他使用 XAML 或基本 XAML 語言支援 (由 System.Xaml 層級的 XAML 語言支援所提供) 的架構。 本主題涵蓋 XAML 概觀 (WPF)主題中介紹的基本術語。

這個主題包含下列章節。

  • XAML 語言規格
  • XAML 和 CLR
  • 物件項目語法
  • 物件項目的屬性
  • 屬性 (Attribute) 語法 (屬性 (Property))
  • 屬性項目語法
  • 集合語法
  • XAML 內容屬性
  • 內容屬性與集合語法合併
  • XAML 命名空間
  • 標記延伸
  • 附加屬性
  • 附加事件
  • XAML 根項目的結構分析
  • 選擇性和非建議的 XAML 使用方式
  • 相關主題

XAML 語言規格

這裡所定義的 XAML 語法術語也會在 XAML 語言規格內定義或參考。 XAML 是以 XML 為基礎的語言,並且遵循或涵蓋 XML 結構規則。 描述 XML 語言或 XML 文件物件模型時,有些術語是以常用的術語為基礎,或共用這些常用術語。

如需 XAML 語言規格的詳細資訊,請從 Microsoft 下載中心下載 [MS-XAML]

XAML 和 CLR

XAML 是一種標記語言。 common language runtime (CLR) 如名稱所示,會啟用執行階段執行。 XAML 本身不是 CLR 執行階段直接使用的一種通用語言。 您可以將 XAML 想像成支援自己的型別系統。 WPF 使用的特殊 XAML 剖析系統建置於 CLR 和 CLR 型別系統上。 XAML 型別會對應至 CLR 型別,以便在剖析 WPF 的 XAML 時執行個體化執行階段表示。 基於這個理由,雖然在 XAML 語言規格中同樣的語法討論未包含 CLR 型別系統參考,本文件中語法討論的其餘部分仍將包含 CLR 型別系統參考。 根據 XAML 語言規格等級,XAML 型別可能對應至任何其他型別系統,這個型別系統不需要是 CLR,不過這樣一來,就需要建立和使用不同的 XAML 剖析器。

型別成員和類別繼承

顯示為 WPF 型別之 XAML 成員的屬性和事件,通常是繼承自基底型別。 例如,請考慮此範例:<Button Background="Blue" .../>。 如果您曾經查看類別定義、反映 (Reflection) 結果或說明文件,就會發現 Background 屬性不是 Button 類別上直接宣告的屬性。 而 Background 是繼承自基底 Control 類別。

WPF XAML 項目的類別繼承行為是 XML 標記之強制執行配置轉譯的重大轉變。 類別繼承可能會變得很複雜,尤其是在中繼基底類別是抽象類別,或是在涉及到介面時。 這就是為何在使用一般用於 XML 程式設計的結構描述類型 (例如 DTD 或 XSD 格式) 時,很難正確而完整地表示 XAML 項目和其可允許的屬性 (Attribute) 組的其中一個原因。 另一個原因是 XAML 語言本身的擴充性和型別對應功能,造成光靠固定表示是無法完整表示可允許的型別和成員的。

物件項目語法

「物件項目語法」(Object Element Syntax) 是 XAML 標記語法,會藉由宣告 XML 項目的方式執行個體化 CLR 類別或結構。 此語法類似於其他標記語言 (如 HTML) 的項目語法。 物件項目語法是以左角括弧 (<) 開頭,後面緊接著要執行個體化之類別或結構的型別名稱。 型別名稱後可以跟隨零或多個空白,而且物件項目也可以宣告零或多個屬性 (Attribute),其中會以一個或多個空白區隔每對「屬性名稱="值"」。 最後,下列其中一個條件必須成立:

  • 項目和標記 (Tag) 必須以正斜線 (/) 再緊接著右角括弧 (>) 結束。

  • 開頭標記必須以右角括弧 (>) 結束。 其他物件項目、屬性 (Property) 項目或內部文字可以跟在開頭標記之後。 這裡可以包含的確切內容,通常會受項目的物件模型所限制。 物件項目的對等結尾標記也必須存在,而且在巢狀結構中需適當配置,並與其他的開頭和結尾標記成對對稱。

由 .NET 實作的 XAML 有一組規則,這些規則會將物件項目對應至型別、屬性 (Attribute) 對應至屬性 (Property) 或事件,並將 XAML 命名空間對應至 CLR 命名空間加上組件。 針對 WPF 和 .NET Framework,XAML 物件項目會對應至 Microsoft .NET 型別,如同在參考的組件中所定義,而屬性會對應至這些型別的成員。 當您在 XAML 中參考 CLR 型別時,同樣可存取該型別繼承的成員。

舉例來說,下列範例的物件項目語法會產生 Button 類別的新執行個體,也會指定 Name 屬性 (Attribute) 和該屬性值:

<Button Name="CheckoutButton"/>

下列範例的物件項目語法也包含 XAML 內容屬性語法。 內含的內部文字將用來設定 TextBox XAML 內容屬性 Text

<TextBox>This is a Text Box</TextBox>

內容模型

類別有可能在語法方面支援使用 XAML 物件項目,但只有在該項目是置放於整體內容模型或項目樹狀結構的預期位置時,該項目才能在應用程式或頁面中正確運作。 舉例來說,MenuItem 通常應該只能置放做為 Menu 這類 MenuBase 衍生類別的子項目。 特定項目之內容模型的說明資訊,會記錄在控制項的類別頁面以及可以用做 XAML 項目的其他 WPF 類別的備註部分。

物件項目的屬性

XAML 中的屬性可透過各種不同的語法設定。 特定屬性該使用哪種語法,會依據您所設定屬性的基礎型別系統特性而有所不同。

藉由設定屬性值,您即可對執行階段物件圖形中的現有物件加入功能或特性。 從物件項目建立之物件的初始狀態,是依據預設建構函式行為而定。 通常應用程式不會完全使用任何特定物件的預設執行個體。

屬性 (Attribute) 語法 (屬性 (Property))

「屬性語法」(Attribute Syntax) 是 XAML 標記語言,會藉由宣告現有物件項目的屬性 (Attribute) 設定屬性 (Property) 值。 屬性 (Attribute) 名稱必須符合支援相關物件項目之類別屬性 (Property) 的 CLR 成員名稱。 屬性 (Attribute) 名稱後會接著指派 (Assignment) 運算子 (=)。 屬性 (Attribute) 值必須是以引號 (") 括住的字串。

注意事項注意事項

您可以使用替代引號在屬性內放置常值引號。例如,您可以使用單引號做為宣告內含雙引號字元之字串的方式。無論您使用單引號或雙引號,都應該使用成對的引號來開始和結束屬性值字串。另外,還有逸出序列或其他方法可用於解決任何特定 XAML 語法所加諸的字元限制。請參閱 XML 字元實體和 XAML

屬性 (Property) 必須是可寫入的公用屬性,才能透過屬性 (Attribute) 語法受到設定。 屬性 (Property) 在支援型別系統中的值必須是實值型別,或必須是參考型別以讓 XAML 處理器在存取相關支援型別時加以執行個體化和參考。

對於 WPF XAML 事件,做為屬性名稱參考的事件必須是公用事件且擁有公用委派。

屬性 (Property) 或事件必須是包含物件項目所產生的類別或結構的成員。

屬性值的處理

成對引號括住的字串是由 XAML 處理器進行處理。 若使用屬性,預設的處理行為是由基礎 CLR 屬性的型別所決定。

屬性 (Attribute) 值必須填入下列其中一個項目,並依這個處理順序:

  1. 如果 XAML 處理器遇到大括號或是衍生自 MarkupExtension 的物件項目,則會先評估參考的標記延伸,而不會以字串進行處理,然後會使用標記延伸傳回的物件。 在許多情況下,標記延伸傳回的物件會是現有物件的參考,或是將評估延後到執行階段而目前非新執行個體化物件的運算式。

  2. 如果屬性 (Property) 是以具有屬性 (Attribute) 的 TypeConverter 宣告的,或是該屬性 (Property) 值的型別是以 TypeConverter 屬性 (Attribute) 宣告的,則屬性 (Attribute) 的字串值會送出給型別轉換子做為轉換輸入,而轉換子會傳回新的物件執行個體。

  3. 如果沒有 TypeConverter,會嘗試屬性型別 (Property Type) 的直接轉換。 這最後一個階段是剖析器原生值在 XAML 語言基本型別之間的直接轉換,或是檢查是否有列舉中具名常數的名稱 (剖析器會接著存取相符的值)。

列舉屬性值

XAML 中的列舉會由 XAML 剖析器以內建方式處理,而列舉成員應藉由指定其中一個列舉之具名常數的字串名稱來指定。

對於非旗標列舉值,原生的行為是處理屬性 (Attribute) 值的字串,並將其解析為其中一個列舉值。 如同在程式碼中的方式一樣,不會以 <列舉>.<值> 的格式指定列舉。 而是只指定 <值>,而 <列舉> 則由您設定的屬性 (Property) 型別推斷。 如果屬性 (Attribute) 是以 <列舉>.<值> 格式指定,將無法正確解析。

對於旗標式的列舉,該行為則是依據 Enum.Parse 方法。 您可以為旗標式的列舉指定多個值,並以逗號分隔每個值。 然而,您不可以結合非旗標式的列舉值。 例如,您無法將逗號語法嘗試使用在建立作用於非旗標列舉的多個條件的 Trigger

<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
  <Setter ... />
</Trigger>
...

在 WPF 中很少有支援可在 XAML 中設定之屬性 (Attribute) 的旗標式列舉。 然而,有一個這類的列舉是 StyleSimulations。 例如,您可以使用逗號分隔的旗標式屬性 (Attribute) 語法修改 Glyphs 類別的註解中提供的範例;StyleSimulations = "BoldSimulation" 可以修改成 StyleSimulations = "BoldSimulation,ItalicSimulation"。 KeyBinding.Modifiers 是另一個可以指定多個列舉值的屬性。 然而這個屬性 (Property) 正好是個特例,因為 ModifierKeys 列舉支援自己的型別轉換子。 修飾詞的型別轉換子會使用加號 (+) 而非逗號 (,) 做為分隔符號。 此轉換作業支援 Microsoft Windows 程式設計中更為傳統的組合鍵代表語法,例如 "Ctrl+Alt"。

屬性和事件成員名稱參考

指定屬性 (Attribute) 時,您可以參考任何屬於您為包含物件項目執行個體化之 CLR 型別成員的屬性 (Property) 或事件。

或者,您也可以參考與包含物件項目無關的附加屬性 (Property) 或附加事件。 附加屬性將在下一節中討論。

如果任何事件是來自可以透過預設命名空間存取的任何物件,您也可以藉由使用 <型別名稱>.<事件> 不完整名稱,為事件命名。這個語法支援路由事件的附加處理常式,其中的處理常式是設計用來處理來自子項目的事件路由,但該事件並不在父項目的成員表中。 這個語法類似於附加事件語法,但這裡的事件並不是真的附加事件。 而您是以完整名稱參考事件。 如需詳細資訊,請參閱路由事件概觀

在某些情況下,屬性 (Property) 名稱有時候是以屬性 (Attribute) 值的形式提供,而非屬性 (Attribute) 名稱。 該屬性 (Property) 名稱也可以包含限定詞,例如以 <擁有者型別>.<相依性屬性名稱> 格式指定的屬性 (Property)。 在 XAML 中撰寫樣式和樣板時,常常會遇到這種情況。 對於以屬性 (Attribute) 值形式提供之屬性 (Property) 名稱的處理規則有許多種,而且是由所要設定屬性 (Property) 的型別或由特定 WPF 子系統的行為所控制。 如需詳細資訊,請參閱設定樣式和範本

屬性 (Property) 名稱另一個使用時機,是在屬性 (Attribute) 值描述屬性 (Property) 對屬性 (Property) 的關係時。 這個功能用於資料繫結和腳本目標,並透過 PropertyPath 類別及其型別轉換子啟用。 如需查閱語意的完整描述,請參閱 PropertyPath XAML 語法

屬性項目語法

「屬性項目語法」(Property Element Syntax) 是與項目的基本 XML 語法規則稍有不同的語法。 XML 中的屬性 (Attribute) 值事實上是字串,唯一可能有的變異在於使用哪種字串編碼格式。 在 XAML 中,您可以指派其他物件項目做為屬性 (Property) 值。 這個功能是藉由屬性 (Property) 項目語法啟用的。 屬性 (Property) 並不會指定為項目標記內屬性 (Attribute),而改以 <項目型別名稱>.<屬性名稱> 格式使用開頭項目標記、在其中指定屬性 (Property) 值,然後再結束屬性 (Property) 項目的方式指定屬性 (Property)。

具體來說就是,語法是以左角括弧 (<) 開頭,緊接著跟隨內含屬性 (Property) 項目語法的類別或結構的型別名稱。 後面緊接著英文句號 (.)、屬性名稱,然後是右角括弧 (>)。 就像在屬性 (Attribute) 語法中一樣,屬性 (Property) 同樣必須存在指定之型別的已宣告公用成員中。 要指派給屬性的值是包含在屬性項目內。 通常會指定一個或多個物件項目做為值,因為將物件指定為值本來就是屬性項目語法要解決的案例。 最後必須提供用於指定相同 <項目型別名稱>.<屬性名稱> 組合的對等結尾標記,而且在巢狀結構中需適當配置,並與其他項目標記對稱。

舉例來說,以下是 ButtonContextMenu 屬性的屬性項目語法。

<Button>
  <Button.ContextMenu>
    <ContextMenu>
      <MenuItem Header="1">First item</MenuItem>
      <MenuItem Header="2">Second item</MenuItem>
    </ContextMenu>
  </Button.ContextMenu>
  Right-click me!</Button>

當指定的屬性型別 (Property Type) 為基本實值型別 (例如 String),或是已指定名稱的列舉時,屬性 (Property) 項目中的值也可以使用內部文字的方式提供。 這兩種使用方式並不常見,因為他們可能也使用更簡單的屬性 (Attribute) 語法。 使用字串填入屬性 (Property) 項目的一個案例,是當屬性 (Property) 不是 XAML 內容屬性 (Property) 卻仍用於表示 UI 文字時,且該 UI 文字中必須出現特殊的空白字元項目,例如換行字元。 屬性 (Attribute) 語法無法保留換行字元,但只要關鍵的空白字元保留是有效的,屬性 (Property) 項目語法就可以保留換行字元 (如需詳細資訊,請參閱 XAML 中的泛空白字元處理)。 另一種情況是為了讓 x:Uid 指示詞 能夠套用至屬性 (Property) 項目,進而將其中的值標記為應該在 WPF 輸出 BAML 中或透過其他方式當地語系化的值。

屬性 (Property) 項目不會出現在 WPF 邏輯樹狀結構中。 屬性 (Property) 項目只是用於設定屬性 (Property) 的特殊語法,並不是具有支援執行個體或物件的項目。 如需邏輯樹狀結構概念的詳細資訊,請參閱 WPF 中的樹狀結構

對於同時支援屬性 (Attribute) 和屬性 (Property) 項目語法的屬性 (Property),這兩種語法通常具有相同的效果,雖然語法間有些微的差異,例如空白字元的處理。

集合語法

XAML 規格需要 XAML 處理器實作,才能識別實值型別是集合的屬性。 .NET 中的一般 XAML 處理器實作是依據 Managed 程式碼和 CLR 進行,並且會透過下列其中一種方式識別集合型別:

如果屬性的型別是集合,則不一定要在標記中指定推斷的集合型別做為物件項目。 但是,設計要成為集合中項目 (Item) 的項目 (Element),會指定為屬性項目 (Element) 的一個或多個子項目 (Element)。 這類的每個項目 (Item) 在載入期間會評估為物件,並且藉由呼叫隱含集合的 Add 方法來加入集合。 例如,StyleTriggers 屬性會採用專屬的集合型別 TriggerCollection,該型別會實作 IList。 不過,不需要在標記中產生 TriggerCollection 物件項目。 而是改為將一個或多個 Trigger 項目 (Item) 指定為 Style.Triggers 屬性項目 (Element) 內的項目 (Element),其中的 Trigger (或衍生類別) 的型別預期是強式型別和隱含 TriggerCollection 的項目 (Item) 型別。

<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
  <Style.Triggers>
    <Trigger Property="Button.IsMouseOver" Value="true">
      <Setter Property = "Background" Value="Red"/>
    </Trigger>
    <Trigger Property="Button.IsPressed" Value="true">
      <Setter Property = "Foreground" Value="Green"/>
    </Trigger>
  </Style.Triggers>
</Style>

屬性可以同時是集合型別,以及該型別和衍生型別的 XAML 內容屬性 (將在本主題的下一節中討論)。

隱含集合項目 (Element) 會在邏輯樹狀結構表示中建立成員,即使它在標記中並未顯示為項目 (Element)。 通常,父型別的建構函式會執行個體化其中一個屬性的集合,而原本的空集合會成為物件樹狀結構的一部分。

注意事項注意事項

偵測集合時,並不支援泛型清單和字典介面 (IList<T>IDictionary<TKey, TValue>)。然而您可以使用 List<T> 類別做為基底類別,因為它直接實作 IList,或是使用 Dictionary<TKey, TValue> 做為基底類別,因為它直接實作 IDictionary

在集合型別的 .NET 參考頁面中,如果語法具有刻意省略的集合物件項目,則有時候會在 XAML 語法章節中標註為<隱含集合語法>。

除了根項目是例外之外,XAML 檔案中每個巢狀在另一個項目下做為子項目的物件項目,實際上會屬於下列情況中的一或兩者:其父項目的隱含集合屬性成員,或者是用於指定父項目的 XAML 內容屬性值的項目 (下一節將討論 XAML 內容屬性)。 換句話說,標記頁面中的父項目 (Element) 和子項目 (Element) 關係實際上是根項目上的單一物件,而根項目下的每個物件項目 (Element),不是提供父項目 (Element) 屬性值的單一執行個體,就是集合內的其中一個項目 (Item) (亦為父項目的集合型別屬性值)。 此單一根概念與 XML 共通,而且經常會在載入 XAML 的 API (如 Load) 行為受到強化。

下列範例的語法中,會明確指定 GradientStopCollection 集合的物件項目。

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="Blue" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

請注意,不一定能夠明確宣告集合。 例如,嘗試在上面顯示的 Triggers 範例中明確宣告 TriggerCollection 就會失敗。 若要明確宣告集合,則集合類別必須支援預設的建構函式,且 TriggerCollection 沒有預設的建構函式。

XAML 內容屬性

XAML 內容語法只會在將 ContentPropertyAttribute 指定為類別宣告一部分的類別上啟用。 ContentPropertyAttribute 參考的屬性名稱,是該型別項目 (包括衍生類別) 的內容屬性。 經過 XAML 處理器處理時,在物件項目的開頭和結尾標記間的任何子項目或內部文字,將會指派為該物件之 XAML 內容屬性的值。 您可以為內容屬性指定明確的屬性項目,但是這種用法通常不會在 .NET 參考的 XAML 語法區段中顯示。 這項明確/詳細資訊技術在標記的清晰度或在做為標記樣式時有其價值,但通常內容屬性的目的是要簡化標記,讓直覺性關聯為父子項目的項目能夠直接形成巢狀結構。 項目上代表其他屬性的屬性項目標記不會指派為「內容」,這是受限於嚴格的 XAML 語言定義。這些標記先前已依 XAML 剖析器的處理順序受到處理,而不會被視為「內容」。

XAML 內容屬性值必須是連續

XAML 內容屬性值,必須在該物件項目上的任何其他屬性項目之前或之後完整指定。 不論 XAML 內容屬性值是指定為字串或是指定為一個或多個物件都是如此。 例如,下列標記無法剖析:

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

這在本質上是不合法的,因為如果這個語法是藉由使用內容屬性的屬性項目語法而明確撰寫的,則設定了兩次該內容屬性:

<Button>
  <Button.Content>I am a </Button.Content>
  <Button.Background>Blue</Button.Background>
  <Button.Content> blue button</Button.Content>
</Button>

類似的不合法範例是當內容屬性是集合時,子項目卻穿插在屬性項目間:

<StackPanel>
  <Button>This example</Button>
  <StackPanel.Resources>
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
  </StackPanel.Resources>
  <Button>... is illegal XAML</Button>
</StackPanel>

內容屬性與集合語法合併

為了能夠接受一個以上的物件項目做為內容,內容屬性的型別必須特別是集合型別。 與集合型別的屬性項目語法類似,XAML 處理器必須辨識屬於集合型別的型別。 如果項目有 XAML 內容屬性,且 XAML 內容屬性的型別為集合,則隱含的集合型別不需要在標記中指定為物件項目,且 XAML 內容屬性不需要指定為屬性項目。 因此,現在標記中的內容模型在外觀上可以有一個以上的子項目指派做為內容。 下列為 Panel 衍生類別的內容語法。 所有 Panel 衍生類別都會將 XAML 內容屬性建立為 Children,且其需要型別 UIElementCollection 的值。

<Page
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>

請注意,標記 (Markup) 中既不需要 Children 的屬性項目,也不需要 UIElementCollection 的項目。 這是 XAML 設計上的功能,因此定義 UI 的遞迴包含項目可以使用直接的父子項目關聯性,更為直覺地以巢狀項目的樹狀結構表示,而不需要插入屬性項目標記或集合物件。 事實上,根據設計,在標記中不能將 UIElementCollection 明確指定為物件項目。 因為它唯一的使用目的是做為隱含集合,UIElementCollection 不會公開公用預設建構函式,因而無法以物件項目產生。

具有內容屬性的物件中的混合屬性項目和物件項目

針對用來在物件項目內填入 XAML 內容屬性的物件項目,XAML 規格會宣告 XAML 處理器可以強制讓該物件項目必須是連續的,而且不能混合物件項目。 這項針對混合屬性項目和內容的限制,是由 WPF XAML 處理器強制執行。

您可以讓子物件項目做為物件項目內的第一個直接標記。 然後引入屬性項目。 或者,您可以指定一個或多個屬性項目,接著是內容,然後是多個屬性項目。 但只要內容後面接著屬性項目,您就不能引入任何進一步的內容,而只能加入屬性項目。

這項內容/屬性項目的順序要求,並不適用於將內部文字用來做為內容的情形。 然而,讓內部文字保持連續仍然是較好的標記樣式,因為在內部文字中穿插屬性項目時,標記中的重要空白字元在視覺上很難偵測。

XAML 命名空間

前述的語法範例指定的 XAML 命名空間,都沒有超出預設 XAML 命名空間的範圍。 在一般的 WPF 應用程式中,預設的 XAML 命名空間會指定為 WPF 命名空間。 您可以指定預設 XAML 命名空間以外的 XAML 命名空間,而仍然使用類似語法。 但是,只要類別是命名在無法從預設 XAML 命名空間內存取的地方,該類別名稱前面就必須加上 XAML 命名空間的前置字元,以對應至 CLR 命名空間。 例如,<custom:Example/> 為物件項目語法,用於執行個體化 Example 類別的執行個體,其中,包含該類別 (甚至是包含支援型別的外部組件資訊) 的 CLR 命名空間已事先對應至 custom 前置字元。

如需 XAML 命名空間的詳細資訊,請參閱 WPF XAML 的 XAML 命名空間和命名空間對應

標記延伸

XAML 定義的「標記延伸」(Markup Extension) 程式設計實體 (Entity),可以逸出字串屬性值或物件項目的一般 XAML 處理器處理,並將處理延後到支援類別中。 在使用屬性語法時,用於識別 XAML 處理器標記延伸的字元,是一個左大括號 ({),再加上右大括號 (}) 以外的任何其他字元。 左大括號後接的第一個字串必須參考提供特定延伸行為的類別,如果子字串是真實類別名稱的一部分,則這裡的參考可以省略子字串 "Extension"。 之後,可以保留一個空格,然後每個後續字元都可以做為延伸實作的輸入,直到遇到右大括號為止。

.NET XAML 實作會使用 MarkupExtension 抽象類別,做為 WPF 以及其他架構或技術所支援之所有標記延伸的基礎。 WPF 特別實作的延伸標記,通常是為了提供一個途徑來參考其他現有物件,或是要延後參考到了執行階段才要評估的物件。 例如,若要完成簡單的 WPF 資料繫結,可以指定 {Binding} 標記延伸來取代特定屬性通常會採用的值。 許多 WPF 標記延伸讓屬性 (Property) 可以在非得使用屬性 (Attribute) 語法的情況下使用屬性 (Attribute) 語法。 例如,Style 物件是一個相當複雜的型別,其中包含一系列的巢狀物件和屬性。 WPF 中的樣式通常會定義在 ResourceDictionary 中做為資源,然後再透過兩種用於要求資源的 WPF 標記延伸中的一種來參考。 標記延伸會將屬性 (Property) 值的評估延後到資源查閱,以下列範例中的屬性 (Attribute) 語法提供 Style 屬性 (Property) 值、採用型別 Style

<Button Style="{StaticResource MyStyle}">My button</Button>

其中,StaticResource 會識別提供標記延伸實作的 StaticResourceExtension 類別。 下一個字串 MyStyle 是用來做為非預設 StaticResourceExtension 建構函式的輸入,其中從延伸字串取得的參數會宣告要求的 ResourceKey。 MyStyle 預期是定義做為資源之 Stylex:Key 值。 StaticResource 標記延伸使用方式要求將資源用於在載入時間 (Load Time) 透過靜態資源查閱邏輯來提供 Style 屬性 (Property) 值。

如需標記延伸的詳細資訊,請參閱標記延伸和 WPF XAML。 如需一般 .NET XAML 實作中啟用之標記延伸和其他 XAML 程式設計功能的參考,請參閱 XAML 命名空間 (x:) 語言功能。 如需 WPF 專用標記延伸,請參閱 WPF XAML 擴充功能

附加屬性

附加屬性 (Property) 是 XAML 中引入的程式設計概念,在這個概念下,特殊型別可以擁有和定義屬性 (Property),但是屬性 (Property) 可以在任何項目上設為屬性 (Attribute) 或屬性項目 (Property Element)。 附加屬性設計上的主要案例是讓標記結構中的子項目,可以回報資訊給父項目,而不需要在所有項目上廣泛地共用物件模型。 反之,附加屬性也可以由父項目用來回報資訊給子項目。 如需附加屬性設計目的和如何建立自己的附加屬性的詳細資訊,請參閱附加屬性概觀

附加屬性使用的語法有一點類似屬性項目語法,其中您也是指定 <型別名稱>.<屬性名稱> 的組合。 但是有兩個重大差異:

  • 即使在透過屬性 (Attribute) 語法設定附加屬性 (Property) 時,您還是可以使用 <型別名稱>.<屬性名稱> 組合。 而附加屬性 (Property) 是唯一要求要限定屬性 (Property) 名稱的屬性 (Attribute) 語法案例。

  • 您也可以為附加屬性 (Property) 使用屬性項目語法。 然而,對於一般的屬性項目語法,您指定的 <型別名稱> 是包含屬性項目的物件項目。 如果參考的是附加屬性,則 <型別名稱> 是定義附加屬性的類別,而不是包含物件項目。

附加事件

附加事件是 XAML 中引入的另一個程式設計概念,在這個概念下,特定型別可以定義事件,但處理常式卻可能附加到任何物件項目上。 在 WOF 實作中,通常定義附加事件的型別是定義服務的靜態型別,而有時候那些附加事件是由公開服務的型別中的路由事件別名所公開。 附加事件的處理常式是透過屬性 (Attribute) 語法而指定的。 與附加事件一起使用時,屬性 (Attribute) 語法會為附加事件展開以允許使用 <型別名稱>.<事件名稱>,其中 <型別名稱> 是針對附加事件基礎結構提供 Add 和 Remove 事件處理常式存取子的類別,而 <事件名稱> 則是事件名稱。

XAML 根項目的結構分析

下表顯示一般的 XAML 根項目細項,代表根項目的特定屬性 (Attribute):

<Page

根項目的開頭物件項目

xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"

預設 (WPF) XAML 命名空間

xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"

XAML 語言 XAML 命名空間

x:Class="ExampleNamespace.ExampleCode"

部分類別宣告,將標記連接至針對該部分類別所定義的任何程式碼後置

>

根之物件項目的結尾。 但物件因為項目包含子項目而尚未結束

選擇性和非建議的 XAML 使用方式

下列各節所說明的 XAML 用法是在技術上可為 XAML 處理器所支援的用法,但是在您開發含有 XAML 原始碼的應用程式時,這些用法會產生版面冗雜或其他有礙觀瞻的問題,造成讀者不易看懂 XAML 檔案。

選擇性的屬性項目使用方式

選擇性的屬性項目使用方式包括明確撰寫 XAML 處理器視為隱含的項目內容屬性。 例如,當您宣告 Menu 的內容時,可以選擇將 MenuItems 集合明確宣告為 <Menu.Items> 屬性項目標記,然後在 <Menu.Items> 中加入每個 MenuItem,而不是使用隱含的 XAML 處理器行為,在其中 Menu 的所有子項目都必須是 MenuItem 並置放在 Items 集合中。 有時候,選擇性的使用方式有助於以視覺方式釐清標記 (Markup) 中呈現的物件結構。 或者,有時候明確屬性 (Property) 項目使用方式可以避免在技術上具有功能、卻會在視覺上造成混淆的標記 (Markup),例如屬性 (Attribute) 值內的巢狀標記延伸。

完整的 typeName.memberName 屬性

屬性的 <型別名稱>.<成員名稱> 格式實際上可應用在更廣泛的範圍,而不只限於路由事件。 但在其他情況下,這樣的格式會太多餘,因次僅就標記版面的美觀性和可讀性來看,應該加以避免。 在下列範例中,對於 Background 屬性的三個參考,其實都是完全相等的:

<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>

Button.Background 能夠運作的原因是,在 Button 上該屬性的限定查閱是成功的 (Background 繼承自 Control),而 Button 是物件項目的類別或基底類別。 Control.Background 能夠運作的原因是,實際定義 BackgroundControlControl 類別是 Button 基底類別。

然而,下列 <型別名稱>.<成員名稱> 格式範例則無法運作,因此顯示為註解:

<!--<Button Label.Background="Blue">Does not work</Button> -->

LabelControl 的另一個衍生類別,而且如果已經在 Label 物件項目內指定 Label.Background,則這種使用方式應該可以運作。 然而,由於 Label 不是 Button 的類別或基底類別,因此指定的 XAML 處理器行為就會接著將 Label.Background 當做附加屬性處理。 不過 Label.Background 並不是可用的附加屬性,所以這個使用方式會失敗。

baseTypeName.memberName 屬性項目

有關 <型別名稱>.<成員名稱> 格式針對屬性 (Attribute) 語法的運作方式,就好比 <基底型別名稱>.<成員名稱> 語法針對屬性 (Property) 項目語法的運作方式。 例如,下列語法即可以運作:

<Button>Control.Background PE
  <Control.Background>
    <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
      <GradientStop Color="Yellow" Offset="0.0" />
      <GradientStop Color="LimeGreen" Offset="1.0" />
    </LinearGradientBrush>
    </Control.Background>
</Button>

即使屬性 (Property) 項目已包含在 Button 中,這裡的屬性 (Property) 項目指定為 Control.Background。

但就像屬性 (Attribute) 的 <型別名稱>.<成員名稱> 格式,<基底型別名稱>.<成員名稱> 是不好的標記樣式,應避免使用。

請參閱

概念

XAML 概觀 (WPF)

相依性屬性概觀

TypeConverter 和 XAML

WPF 的 XAML 和自訂類別

其他資源

XAML 命名空間 (x:) 語言功能

WPF XAML 擴充功能