WPF學習------XAML 語法詳述

XAML 語言規範中也定義或引用了此處定義的 XAML 語法術語。 XAML 是一種基於 XML 並遵循或擴展 XML 結構規則的語言。 其中某些術語共享自或基於描述 XML 語言或 XML 文檔對象模型時常用的術語。

有關 XAML 語言規範的更多信息,請從 Microsoft 下載中心下載 [MS-XAML]

XAML 是一種標記語言。 顧名思義,公共語言運行時 (CLR) 實現了運行時執行。 XAML 本身並非 CLR 運行時直接使用的一種公共語言。 而是可以將 XAML 視爲支持其自身的類型系統。 WPF 所使用的特定 XAML 分析系統是根據 CLR 和 CLR 類型系統構建的。 在分析 WPF 的 XAML 時,XAML 類型將映射到 CLR 類型,以便將運行時表示形式實例化。 出於此原因,本文檔中語法討論的其餘部分將包括對 CLR 類型系統的引用,而 XAML 語言規範中並未就這部分語法展開討論。 (在 XAML 語言規範的每個級別,XAML 類型都可以映射到任何其他類型系統,而不一定要映射到 CLR,但這需要創建和使用一種不同的 XAML 分析器。)

ms788723.collapse_all(zh-cn,VS.110).gif類型成員和類繼承

屬性和事件在作爲 WPF 類型的 XAML 成員時,通常從基類型繼承而來。 請考慮此代碼示例:<Button Background="Blue" .../> 如果要查看類定義、反射結果或文檔,則Background 屬性並不是 Button 類上立即聲明的屬性。 相反,Background 是從基 Control 類繼承而來。

WPF XAML 元素的類繼承行爲與架構對 XML 標記的強制解釋大相徑庭。 類繼承可能會變得很複雜,特別是在中間基類爲抽象類或涉及到接口的情況下尤爲如此。 由於這樣一個原因,因此很難通過 XML 編程常用的架構類型(例如 DTD 或 XSD 格式)準確並完整地表示 XAML 元素及其所允許特性的集合。 另一個原因是,XAML 語言本身的擴展性和類型映射功能會對所允許類型和成員的任何固定表示形式的完整性造成妨礙。

對象元素語法是一種 XAML 標記語法,它通過聲明 XML 元素將 CLR 類或結構實例化。 這種語法類似於如 HTML 等其他標記語言的元素語法。 對象元素語法以左尖括號 (<) 開始,後面緊跟要實例化的類或結構的類型名稱。 類型名稱後面可以有零個或多個空格,對於對象元素還可以聲明零個或多個特性,並用一個或多個空格來分隔每個“特性名="值"”對。 最後,必須存在下列一種情況:

  • 元素和標記必須用正斜槓 (/) 和緊跟的右尖括號 (>) 結尾。

  • 開始標記必須以右尖括號 (>) 結尾。 其他對象元素、屬性元素或內部文本可以跟在開始標記後面。 此處可以包含的確切內容通常會受到元素對象模型的約束。 對象元素還必須存在等效的結束標記,並與其他開始標記/結束標記對形成正確的嵌套和平衡。

由 .NET 實現的 XAML 具有一組規則,可將對象元素映射爲類型、將特性映射爲屬性或事件,以及將 XAML 命名空間映射到 CLR 命名空間和程序集。 對於 WPF 和 .NET Framework,XAML 對象元素映射到 Microsoft .NET 類型(如引用的程序集中所定義),而特性映射到這些類型的成員。 在 XAML 中引用 CLR 類型時,還可以訪問該類型的繼承成員。

例如,下面的示例是一個對象元素語法,該語法實例化 Button 類的一個新實例,而且還指定了一個 Name 特性及其值:

<Button Name="CheckoutButton"/>


下例是其中也包括 XAML 內容屬性語法的對象元素語法。 其中包含的內部文本將用於設置 TextBox 的 XAML 內容屬性 Text

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


ms788723.collapse_all(zh-cn,VS.110).gif內容模型

從語法上講,類可能支持作爲 XAML 對象元素的用途,但只有將該元素放置在整體內容模型或元素樹中的應有位置時,該元素才能在應用程序或頁面中發揮正常的作用。 例如,MenuItem 通常只應作爲 MenuBase 派生類(如 Menu)的子級放置。 在可用作 XAML 元素的控件和其他 WPF 類的類頁面上,將特定元素的內容模型記錄爲備註的一部分。

XAML 中的屬性是由多種可能的語法設置的。 根據所設置屬性的基礎類型系統的特徵,可用於特定屬性的語法將有所不同。

通過設置屬性值,可以在對象存在於運行時對象圖中時爲對象添加功能或特徵。 從對象元素中創建的對象的初始狀態基於默認的構造函數行爲。 通常,您的應用程序將使用其他一些實例,而不是任何給定對象的完全默認的實例。

特性語法是一種 XAML 標記語法,該語法聲明現有對象元素中的特性,從而設置屬性的值。 特性名稱必須與支持相關對象元素的類的屬性的 CLR 成員名稱相匹配。 特性名稱後面跟隨一個賦值運算符 (=)。 特性值必須是用引號引起來的字符串。

說明 說明

可以使用替代引號在特性中放置文本引號。 例如,可以使用單引號作爲聲明其中包含雙引號字符的字符串的一種方法。 無論使用單引號還是雙引號,對於開始和結束特性值字符串都應該使用一對匹配的字符。 還有一些轉義序列或其他技術可用於解決任何特定 XAML 語法規定的字符限制。 請參見 XML 字符實體和 XAML

爲了通過特性語法進行設置,屬性必須爲公共屬性,並且必須可寫。 後備類型系統中屬性的值必須爲值類型,或者必須爲可由 XAML 處理器在訪問相關後備類型時實例化或引用的引用類型。

對於 WPF XAML 事件,作爲特性名稱被引用的事件必須是公共事件,並且必須具有公共委託。

屬性或事件必須是由包含對象元素實例化的類或結構的成員。

ms788723.collapse_all(zh-cn,VS.110).gif特性值的處理

左右引號內包含的字符串值由 XAML 處理器進行處理。 對於屬性,默認處理行爲由基礎 CLR 屬性的類型確定。

特性值由下面的操作之一,按照如下處理順序進行填充:

  1. 如果 XAML 處理器遇到大括號或從 MarkupExtension 派生的對象元素,則首先計算引用的標記擴展(而不是將值作爲字符串進行處理),然後使用該標記擴展返回的對象作爲值。 在許多情況下,標記擴展返回的對象是對現有對象的引用或是將計算推遲到運行時的表達式,而不是新實例化的對象。

  2. 如果屬性是用特性化 TypeConverter 聲明的,或者該屬性的值類型是用特性化 TypeConverter 聲明的,則該特性的字符串值將作爲轉換輸入提交到類型轉換器,然後轉換器將返回新的對象實例。

  3. 如果沒有 TypeConverter,則將嘗試直接轉換爲屬性類型。 此最終級別是在 XAML 語言基元類型之間直接轉換本身具有分析器的值、或檢查枚舉(分析器隨後將訪問匹配的值)中命名常量的名稱。

ms788723.collapse_all(zh-cn,VS.110).gif枚舉特性值

XAML 中的枚舉由 XAML 分析器進行內部處理,而枚舉的成員則應該通過指定枚舉的某個命名常量的字符串名稱進行指定。

對於無標誌的枚舉值,本機行爲是處理特性值的字符串並將它解析爲某個枚舉值。 您不必像在代碼中那樣指定格式爲枚舉. 的枚舉, 而是僅指定枚舉 將從所設置屬性的類型推斷。 如果您指定格式爲枚舉. 的特性,它將無法正確解析。

對於按標誌枚舉,該行爲基於 Enum.Parse 方法。 您可以通過用逗號分隔每個值來爲按標誌枚舉指定多個值。 但是,您不能合併不按標誌的枚舉值。 例如,不能嘗試使用逗號語法來創建作用於無標誌枚舉多個條件的 Trigger

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

在 WPF 中,很少有按標誌枚舉能支持可在 XAML 中設置的特性。 但是,StyleSimulations 就是這樣的一個枚舉。 例如,可以使用逗號分隔的按標誌特性語法修改在 Glyphs類的“Remarks”(備註)部分中提供的示例;StyleSimulations = "BoldSimulation" 可以變爲 StyleSimulations = "BoldSimulation,ItalicSimulation" KeyBinding.Modifiers是另一個其中可指定多個枚舉值的屬性。 但是,此屬性恰好是一個特例,因爲 ModifierKeys 枚舉支持其自身的類型轉換器。 修飾符的類型轉換器使用加號 (+) 而不是逗號 (,) 作爲分隔符。 此轉換支持用更傳統的語法表示 Microsoft Windows 編程中的組合鍵(如“Ctrl+Alt”)。

ms788723.collapse_all(zh-cn,VS.110).gif屬性引用和事件成員名稱引用

指定特性時,可以引用作爲您爲包含對象元素實例化的 CLR 類型的成員而存在的任何屬性或事件。

或者,可以獨立於包含對象元素來引用附加屬性或附加事件。 (後面的某節即將討論附加屬性。)

對於可通過默認命名空間訪問的任何對象中的任何事件,還可以通過使用“類型名稱.事件”部分限定名來命名;此語法支持爲路由事件附加處理程序,在路由事件中,處理程序旨在處理子元素中的事件路由,但是父元素在其成員表中並不擁有該事件。 此語法與附加事件語法相似,但此處的事件不是真正的附加事件。 相反,您引用的是具有限定名稱的事件。 有關更多信息,請參見路由事件概述

對於某些情況,屬性名稱有時是以特性的值(而不是特性名稱)的形式提供的。 該屬性名稱還可以包括限定符,例如以所有者類型.依賴項屬性名稱 格式指定的屬性。 在 XAML 中編寫樣式或模板時,此情況較爲常見。 以特性值形式提供的屬性名稱具有不同的處理規則,這些規則由所設置的屬性類型或特定 WPF 子系統的行爲控制。 有關詳細信息,請參見樣式設置和模板化

當特性值描述屬性之間的關係時,也可以使用屬性名。 此功能可用於數據綁定和演示圖板目標,而且由 PropertyPath 類及其類型轉換器啓用。 有關查找語義的更完整說明,請參見 PropertyPath XAML 語法

屬性元素語法是一種與元素的基本 XML 語法規則略有不同的語法。 在 XML 中,特性的值實際上是一個字符串,唯一可能的變化是使用哪種字符串編碼格式。 在 XAML 中,可以指定其他對象元素作爲屬性的值。 此功能由屬性元素語法來啓用。 並不將屬性指定爲元素標記內的特性,而是使用元素的開始標記指定“元素類型名稱.屬性名稱”形式的屬性,在其中指定屬性的值,然後結束屬性元素。

具體而言,該語法以左尖括號 (<) 開頭,其後緊跟包含屬性元素語法的類或結構的類型名稱。 類型名稱後面緊跟一個點 (.),然後跟屬性的名稱,最後跟一個右尖括號 (>)。 對於特性語法,指定類型的已聲明公共成員內必須存在該屬性。 要賦給屬性的值包含在相應的屬性元素中。 通常,值作爲一個或多個對象元素提供,因爲將對象指定爲值正是屬性元素語法應當實現的方案。 最後,必須提供一個等效的結束標記來指定同一個元素類型名稱.屬性名稱 組合,並與其他元素標記對形成正確的嵌套和平衡。

例如,下面的屬性元素語法針對的是 Button 的 ContextMenu 屬性。

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


當要指定的屬性類型是基元值類型(如 String)或是指定了名稱的枚舉時,也可以用內部文本的形式給出屬性元素中的值。 這兩個用法在某種程度上並不常見,因爲這兩種情況都還可以使用更簡單的特性語法。 用字符串填充屬性元素的一個方案是,對於不是 XAML 內容屬性但仍用於表示 UI 文本的屬性,該 UI 文本中必須出現特定的空白元素(如換行符)。 特性語法不能保留換行符,但是屬性元素語法可以保留換行符,不過前提是用來保留大量空白的功能處於活動狀態(有關詳細信息,請參見 XAML 中的空白處理)。另一個方案使 x:Uid 指令可應用於屬性元素,並因此將其中的值標記爲應在 WPF 輸出 BAML 中本地化或通過其他技術本地化的值。

屬性元素不以 WPF 邏輯樹的形式表示。 屬性元素不是由實例或對象支持的元素,而只是一個用來設置屬性的特定語法。 (有關邏輯樹概念的詳細信息,請參見 WPF 中的樹。)

對於同時支持特性語法和屬性元素語法的屬性,儘管這兩種語法的細微之處(如空白處理)略有不同,但它們的結果通常是一樣的。

XAML 規範要求 XAML 處理器實現能標識其中值類型爲集合的屬性。 .NET 中的常規 XAML 處理器實現基於託管代碼和 CLR,並且該處理器實現通過以下各項之一標識集合類型:

如果屬性的類型是集合,則不必在標記中以對象元素的形式指定推斷的集合類型。 而要成爲集合中項的元素將被指定爲屬性元素的一個或多個子元素。 在加載每個此類項的過程中會將該項計算爲對象,然後通過調用隱含集合的 Add 方法將其添加到集合中。 例如,Style 的 Triggers 屬性採用專用的集合類型 TriggerCollection(該類型實現 IList)。不必在標記中將 TriggerCollection 對象元素實例化。 而是需要在 Style.Triggers 屬性元素中指定一個或多個 Trigger 項作爲元素,其中 Trigger(或派生類)是一個類型,應當作爲隱式強類型 TriggerCollection 的項類型。

<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 內容屬性,本主題的下一節將討論這種情況。

隱式集合元素在邏輯樹表示形式中創建一個成員,即使該成員不以元素的形式出現在標記中也是如此。 通常,父類型的構造函數對作爲其屬性之一的集合執行實例化,然後最初爲空的集合將成爲對象樹的一部分。

說明 說明

集合檢測功能不支持泛型列表和字典接口(IList<T> 和 IDictionary<TKey, TValue>)。 但是,可以將 List<T> 類用作基類(因爲它直接實現 IList),或者將Dictionary<TKey, TValue> 用作基類(因爲它直接實現 IDictionary)。

在集合類型的 .NET 參考頁中,這種特意省略集合的對象元素的語法在 XAML 語法部分中有時稱爲“隱式集合語法”。

除了根元素外,XAML 文件中以另一個元素的子元素形式嵌套的每個對象元素實際上都屬於下列一種或兩種情況:父元素的隱式集合屬性的成員,或是爲父元素指定 XAML 內容屬性值的元素(後面的某節即將討論 XAML 內容屬性)。 換言之,一個標記頁上的父元素與子元素之間的關係實際上就是一個根對象,而根對象下面的每個對象元素要麼是爲父元素提供屬性值的一個實例,要麼是同樣作爲父元素的集合類型屬性值的集合中的一項。 這種單根概念對於 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 內容語法作爲一種語法,僅在指定 ContentPropertyAttribute 作爲其類聲明一部分的類上啓用。 ContentPropertyAttribute 引用作爲該類型元素(包括派生類)的內容屬性的內容名稱。 當 XAML 處理器處理在對象元素的開始標記和結束標記之間找到的任何子元素或內部文本時,會向其賦予該對象的 XAML 內容屬性的值。 對於內容屬性允許指定顯式的屬性元素,但 .NET 參考的 XAML 語法章節中一般不介紹這種用法。 這種顯式/詳細的方法有時很實用,可使標記清晰明確或作爲一種重要的標記樣式,但內容屬性的意圖通常是要簡化標記,以便可以直接嵌套直觀相關的父/子元素。 對於元素上其他屬性的屬性元素標記,並不按嚴格的 XAML 語言定義將其指派爲“內容”;這些標記以前是按 XAML 分析器的處理順序進行處理的,並不將其視爲“內容”。

ms788723.collapse_all(zh-cn,VS.110).gifXAML 內容屬性值必須連續

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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  >
  <StackPanel>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
    <Button>Button 3</Button>
  </StackPanel>
</Page>


請注意,標記中既不需要 Children 的屬性元素也不需要 UIElementCollection 的元素。 這是 XAML 的特有設計,其目的是爲了讓用於定義 UI 的遞歸包含元素按緊鄰的父-子元素關係更直觀地表示爲嵌套元素的樹,而不必干預屬性元素標記或集合對象。 實際上,特意使 UIElementCollection 不能在標記中被顯式指定爲對象元素。 由於UIElementCollection 唯一的用途就是作爲隱式集合,因此它不公開公共的默認構造函數,因此不能實例化爲對象元素。

ms788723.collapse_all(zh-cn,VS.110).gif在具有內容屬性的對象中混合使用屬性元素和對象元素

XAML 規範聲明 XAML 處理器可以強制用於填充某個對象元素中 XAML 內容屬性的各個對象元素必須連續,並且不得混合使用。 針對混合使用屬性元素和內容的這一限制由 WPF XAML 處理器強制實施。

可以將子對象元素作爲某個對象元素中的第一個直接標記, 然後可以引入屬性元素。 也可以指定一個或多個屬性元素,接着指定內容,然後指定多個屬性元素。 但是,一旦內容後面跟有屬性元素,您就不能進一步引入任何內容,而只能添加屬性元素。

這個內容/屬性元素順序要求不適用於用作內容的內部文本。 然而,這仍然是使內部文本保持連續的不錯的標記樣式,原因是,如果屬性元素與內部文本交錯分佈,則很難直觀地檢測標記中的大量空白。

上述所有語法示例均未指定默認 XAML 命名空間以外的 XAML 命名空間。 在典型的 WPF 應用程序中,將默認 XAML 命名空間指定爲 WPF 命名空間。 您可以指定默認 XAML 命名空間以外的其他 XAML 命名空間,並仍然使用類似的語法。 但是,只要無法在默認 XAML 命名空間中訪問已命名的類,就必須在該類名稱之前加上映射到對應 CLR 命名空間的 XAML 命名空間的前綴。 例如,<custom:Example/> 是一種用於對 Example 類的實例進行實例化的對象元素語法,其中包含該類的 CLR 命名空間(可能還有包含後備類型的外部程序集信息)以前映射到 custom 前綴。

有關 XAML 命名空間的更多信息,請參見 WPF XAML 的 XAML 命名空間和命名空間映射

XAML 定義了一個標記擴展編程實體,該實體允許從 XAML 處理器對字符串特性值或對象元素的常規處理中進行轉義,並將處理轉交給後備類。 在使用特性語法時,標識 XAML 處理器的標記擴展的字符是左大括號 ({),後接右大括號 (}) 以外的任何字符。 左大括號後面的第一個字符串必須引用用來提供特定擴展行爲的類,如果子字符串“Extension”是實際類名的一部分,則該引用可以省略這個子字符串。 該類後面可能會出現一個空格,該空格後面的每個字符都可以由所實現的擴展用作輸入,直到遇到右大括號。

.NET XAML 實現使用 MarkupExtension 抽象類作爲 WPF 以及所有其他框架或技術支持的所有標記擴展的基礎。 WPF 特定實現的標記擴展通常用於提供一種方法來引用其他已經存在的對象,或者對將在運行時計算的對象進行延遲引用。 例如,通過指定用 {Binding} 標記擴展代替特定屬性通常將採用的值,從而實現簡單的 WPF 數據綁定。 對於無法以其他方式使用特性語法的屬性,許多 WPF 標記擴展都允許使用特性語法。 例如,Style 對象是一種相對複雜的類型,其中包含一系列嵌套的對象和屬性。 WPF 中的樣式通常定義爲 ResourceDictionary 中的資源,之後將通過請求資源的兩個 WPF 標記擴展之一來引用。 標記擴展將屬性值的計算推遲到查找資源時進行,並允許在特性語法中提供Style 屬性的值並採用 Style 類型,如下例所示:

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

在這裏,StaticResource 用來標識 StaticResourceExtension 類,該類提供標記擴展實現。 下一個字符串 MyStyle 用作非默認 StaticResourceExtension 構造函數的輸入,在該構造函數中,從擴展字符串提取的參數將聲明所請求的 ResourceKey MyStyle 應當是定義爲資源的 Style 的 x:Key 值。 StaticResource 標記擴展 用法要求使用該資源,在加載時通過靜態資源查找邏輯來提供 Style 屬性值。

有關標記擴展的更多信息,請參見標記擴展和 WPF XAML。 有關常規 .NET XAML 實現中啓用的標記擴展和其他 XAML 編程功能的參考,請參見 XAML 命名空間 (x:) 語言功能 有關特定於 WPF 的標記擴展,請參見 WPF XAML 擴展

附加屬性是 XAML 中引入的一個編程概念,藉此,特定類型可以擁有和定義屬性,但在任何元素上都將屬性設置爲特性或屬性元素。 附加屬性所面向的主要方案是,允許標記結構中的子元素向父元素報告信息,同時不需要在所有元素之間廣泛共享的對象模型。 相反,附加屬性可以由任何父元素用來向子元素報告信息。 有關附加屬性的用途以及如何創建您自己的附加屬性的更多信息,請參見附加屬性概述

附加屬性使用的語法在表面上與屬性元素語法非常相似,因爲您還需要指定類型名.屬性名 組合。 二者有兩個重要的差異:

  • 即使在通過特性語法設置附加屬性時,也可以使用類型名.屬性名 組合。 只有附加屬性纔要求特性語法中使用限定屬性名。

  • 對於附加屬性還可以使用屬性元素語法。 但是,對於典型的屬性元素語法,您指定的類型名 是包含屬性元素的對象元素。 如果您引用的是附加屬性,則類型名 是用來定義附加屬性的類,而不是包含對象元素。

附加事件是 XAML 中引入的另一個編程概念,其中可以由特定類型定義事件,但處理程序可以附加到任何對象元素上。 在 WPF 實現中,用於定義附加事件的類型通常是用於定義服務的靜態類型,而這些附加事件有時由用於公開服務的類型中的路由事件別名公開。 附加事件的處理程序是通過特性語法指定的。 就附加事件而言,特性語法針對附加事件進行了擴展,以便允許“類型名稱.事件名稱”用法,其中“類型名稱”是爲附加事件基礎結構提供 Add 和 Remove 事件處理程序訪問器的類,而“事件名稱”是事件名稱。

下表顯示了一個經過分解的典型 XAML 根元素,同時顯示了根元素的具體特性:

<Page

根元素的開始對象元素

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

默認 (WPF) XAML 命名空間

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

XAML 語言 XAML 命名空間

x:Class="ExampleNamespace.ExampleCode"

分部類聲明,它將標記連接到爲分部類定義的任何代碼隱藏

>

根的對象元素的末尾。 由於該元素包含子元素,因此對象未結束

以下各節描述 XAML 處理器在技術上支持的 XAML 用法,但這些用法會產生冗長的內容或其他美觀上的問題,當您開發包含 XAML 源的應用程序時,這些問題會對保持可讀的 XAML 文件產生影響。

ms788723.collapse_all(zh-cn,VS.110).gif屬性元素的可選用法

屬性元素的可選用法包括,顯式寫入被 XAML 處理器視爲隱式的元素內容屬性。 例如,聲明 Menu 的內容時,可以選擇將 Menu 的 Items 集合顯式聲明爲 <Menu.Items> 屬性元素標記,並將每個 MenuItem 放置在 <Menu.Items> 中,而不是使用隱式 XAML 處理器行爲(即,Menu 的所有子元素都必須是 MenuItem 而且放置在 Items 集合中)。 有時,這個可選用法可以幫助以可視方式闡明標記中所表示的對象結構。 或者,屬性元素的隱式用法有時可以避免使用在技術上具有功能,但在視覺上容易引起混淆(如在特性值中嵌套標記擴展)的標記。

ms788723.collapse_all(zh-cn,VS.110).giftypeName.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 之所以適用,是因爲 Control 類實際定義了 Background,而且 Control 是 Button 的基類。

但是,下面的類型名.成員名 格式示例並不適用,因此顯示爲已註釋掉:

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


Label 是 Control 的另一個派生類,而且,如果在 Label 對象元素中指定了 Label.Background,則該用法將適用。 但是,由於 Label 不是 Button 的類或基類,因此指定的 XAML 處理器行爲是隨後將 Label.Background 作爲附加屬性進行處理。 Label.Background 不是可用的附加屬性,因此這個用法將失敗。

ms788723.collapse_all(zh-cn,VS.110).gifbaseTypeName.memberName 屬性元素

與“類型名稱.成員名稱”格式如何適用於特性語法類似,“基類型名稱.成員名稱”語法適用於屬性元素語法。 例如,下面的語法適用:

<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>


在這裏,即使屬性元素包含在 Button 中,屬性元素也會以 Control.Background 形式提供。

但是,正如特性的“類型名稱.成員名稱”形式一樣,“基類型.成員名稱”在標記中不是良好的樣式,應當避免使用這種形式。

發佈了17 篇原創文章 · 獲贊 9 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章