WPF基础之XAML
本主題介紹可擴(kuò)展應(yīng)用程序標(biāo)記語(yǔ)言 (XAML) 語(yǔ)言的功能,并演示如何使用 XAML 編寫 Windows Presentation Foundation (WPF) 應(yīng)用程序。本主題專門介紹了 Windows Presentation Foundation (WPF) 實(shí)現(xiàn)的 XAML。XAML 本身是比 Windows Presentation Foundation (WPF) 更廣泛的一個(gè)語(yǔ)言概念。
具有流控制支持的聲明性語(yǔ)言 XAML 簡(jiǎn)化了為 .NET Framework 編程模型創(chuàng)建 UI 的過(guò)程。您可以在聲明性 XAML 標(biāo)記中創(chuàng)建可見的 UI 元素,然后使用代碼隱藏文件(通過(guò)分部類定義與標(biāo)記相連接)將 UI 定義與運(yùn)行時(shí)邏輯相分離。在 XAML 中混合代碼和標(biāo)記的功能很重要,因?yàn)?XML 本身是聲明性的,不會(huì)為流控制真正建議一個(gè)模型。基于 XML 的聲明性語(yǔ)言非常直觀,可以為用戶(尤其是具有 Web 設(shè)計(jì)和技術(shù)背景的人員)創(chuàng)建從原型到生產(chǎn)的各種界面。與其他大多數(shù)標(biāo)記語(yǔ)言不同,XAML 直接呈現(xiàn)托管對(duì)象的實(shí)例化。這種常規(guī)設(shè)計(jì)原則簡(jiǎn)化了使用 XAML 創(chuàng)建的對(duì)象的代碼和調(diào)試訪問(wèn)。
XAML 文件是指通常使用 .xaml 擴(kuò)展名的 XML 文件。
下面的 XAML 示例演示了小標(biāo)記在創(chuàng)建作為 UI 一部分的按鈕時(shí)的必要性。創(chuàng)建的按鈕通過(guò)主題樣式獲得默認(rèn)的可視化表示形式,通過(guò)其類設(shè)計(jì)獲得默認(rèn)的行為。
XAML 對(duì)象元素 XAML 有一組規(guī)則,這些規(guī)則將對(duì)象元素映射為類或結(jié)構(gòu),將屬性 (Attribute) 映射為屬性 (Property) 或事件,并將 XML 命名空間映射為 CLR 命名空間。XAML 元素映射為被引用程序集中定義的 Microsoft .NET 類型,而屬性 (Attribute) 則映射為這些類型的成員。
上面的示例指定了兩個(gè)對(duì)象元素:<STACKPANEL>(具有一個(gè)結(jié)束標(biāo)記)和<BUTTON>同樣具有多個(gè)屬性;下一節(jié)將介紹屬性)。字符串 StackPanel 和 Button 都將映射為某個(gè)類的名稱,該類由 WPF 定義并且是 WPF 程序集的一部分。在指定對(duì)象元素標(biāo)記時(shí),可以為 XAML 處理創(chuàng)建一條指令,以便在加載 XAML 頁(yè)時(shí)創(chuàng)建指定類的一個(gè)新實(shí)例。每個(gè)實(shí)例都是通過(guò)調(diào)用基礎(chǔ)類或結(jié)構(gòu)的默認(rèn)構(gòu)造函數(shù)并對(duì)結(jié)果進(jìn)行存儲(chǔ)而創(chuàng)建的。為了可用作 XAML 中的對(duì)象元素,該類或結(jié)構(gòu)必須公開一個(gè)公共的默認(rèn)(無(wú)參數(shù))構(gòu)造函數(shù)。
?
設(shè)置屬性 XAML 中的屬性是通過(guò)使用各種可能的語(yǔ)法在對(duì)象元素上設(shè)置屬性來(lái)設(shè)置的。根據(jù)所設(shè)置的屬性的特征,給定屬性可使用的語(yǔ)法會(huì)有所不同。
通過(guò)設(shè)置屬性值,可以為對(duì)象元素添加功能或特征。對(duì)象元素的基礎(chǔ)對(duì)象實(shí)例的初始狀態(tài)基于默認(rèn)的構(gòu)造函數(shù)行為。通常,您的應(yīng)用程序?qū)⑹褂闷渌恍?shí)例,而不是任何給定對(duì)象的完全默認(rèn)的實(shí)例。
屬性語(yǔ)法 在 XAML 中,屬性 (Property) 常常可以表示為屬性 (Attribute)。屬性 (Attribute) 語(yǔ)法是最簡(jiǎn)單的屬性 (Property) 設(shè)置語(yǔ)法,并將成為過(guò)去使用標(biāo)記語(yǔ)言的開發(fā)人員可以使用的最直觀的語(yǔ)法。例如,以下標(biāo)記將創(chuàng)建一個(gè)具有紅色文本和藍(lán)色背景的按鈕,還會(huì)創(chuàng)建指定為 Content 的顯示文本。
屬性元素語(yǔ)法 對(duì)于一個(gè)對(duì)象元素的某些屬性 (Property),屬性 (Attribute) 語(yǔ)法是不可能實(shí)現(xiàn)的,因?yàn)樘峁傩?(Property) 值所需的對(duì)象或信息不能充分地表示為簡(jiǎn)單的字符串。對(duì)于這些情況,可以使用另一個(gè)語(yǔ)法,即屬性元素語(yǔ)法。屬性元素語(yǔ)法用標(biāo)記的內(nèi)容設(shè)置包含元素的引用的屬性。一般而言,內(nèi)容就是作為屬性值的類型的某個(gè)對(duì)象(值設(shè)置實(shí)例通常被指定為另一個(gè)對(duì)象元素)。屬性元素本身的語(yǔ)法為 <類型名稱.屬性>。指定內(nèi)容之后,必須用一個(gè)結(jié)束標(biāo)記結(jié)束屬性元素,就像其他任何元素(語(yǔ)法為 )一樣。對(duì)于同時(shí)支持屬性 (Attribute) 和屬性 (Property) 元素語(yǔ)法的屬性 (Property),盡管這兩種語(yǔ)法的細(xì)微之處(如空白處理)略有不同,但它們的結(jié)果通常是一樣的。如果可以使用屬性 (Attribute) 語(yǔ)法,那么使用屬性 (Attribute) 語(yǔ)法通常更為方便,且能夠?qū)崿F(xiàn)更為精簡(jiǎn)的標(biāo)記,但這只是一個(gè)風(fēng)格的問(wèn)題,而不屬于技術(shù)限制。下面的示例演示了在前面的屬性 (Attribute) 語(yǔ)法示例中設(shè)置的相同屬性 (Property),但這次對(duì) Button 的所有屬性 (Property) 使用了屬性 (Property) 元素語(yǔ)法。
XAML 的屬性 (Property) 元素語(yǔ)法表示了與標(biāo)記的基本 XML 解釋之間的巨大背離。對(duì)于 XML,<類型名稱.屬性> 代表了另一個(gè)元素,該元素僅表示一個(gè)子元素,而與 TypeName 父級(jí)之間沒(méi)有必然的隱含關(guān)系。在 XAML 中,<類型名稱.Property> 直接表示 Property 是類型名稱 的屬性(由屬性元素內(nèi)容設(shè)置),而絕不會(huì)是一個(gè)名稱相似(碰巧名稱中有一個(gè)點(diǎn))但卻截然不同的元素。
屬性和類繼承 作為 WPF 元素的XAML 屬性 (Attribute) 而出現(xiàn)的屬性 (Property) 通常從基類繼承而來(lái)。例如,在上一個(gè)示例中,如果您要查看類定義、反射結(jié)果或文檔,Background 屬性并不是在 Button 類上直接聲明的屬性。相反,Background 是從基 Control 類繼承而來(lái)。
WPF XAML 元素的類繼承行為是與標(biāo)記的基本 XML 解釋之間的另一個(gè)巨大背離。使用類繼承(尤其是中間基類為抽象類時(shí))的另一個(gè)原因在于,通過(guò) XML 編程常用的架構(gòu)類型(如 DTD 或 XSD 格式)幾乎不可能準(zhǔn)確且完整地表示 XAML 元素及其允許屬性集。另外,XAML 中的“X”表示“extensible”(可擴(kuò)展),而可擴(kuò)展性破壞了“什么是用于 WPF 的 XAML”的任何給定表示形式的完整性。
引用值和標(biāo)記擴(kuò)展 標(biāo)記擴(kuò)展是一個(gè) XAML 概念。在屬性語(yǔ)法中,花括號(hào)({ 和 })表示標(biāo)記擴(kuò)展用法。此用法指示 XAML 處理不要像通常那樣將屬性值視為一個(gè)字符串或者可直接轉(zhuǎn)換為文本字符串的值。
當(dāng)屬性采用引用類型值時(shí),這些屬性常常需要屬性元素語(yǔ)法(始終創(chuàng)建一個(gè)新實(shí)例)或通過(guò)標(biāo)記擴(kuò)展的對(duì)象引用。標(biāo)記擴(kuò)展用法有可能會(huì)返回現(xiàn)有實(shí)例,因此可以更加多樣化,或者產(chǎn)生較少的對(duì)象系統(tǒng)開銷。
當(dāng)使用標(biāo)記擴(kuò)展提供屬性值時(shí),應(yīng)改為由相關(guān)標(biāo)記擴(kuò)展的后備類中的邏輯提供屬性值。WPF 應(yīng)用程序編程中最常用的標(biāo)記擴(kuò)展是 Binding(用于數(shù)據(jù)綁定表達(dá)式)以及資源引用 StaticResource 和 DynamicResource。通過(guò)使用標(biāo)記擴(kuò)展,即使屬性 (Property) 不支持對(duì)直接對(duì)象實(shí)例化使用屬性 (Attribute) 語(yǔ)法,也可以使用屬性 (Attribute) 語(yǔ)法為屬性 (Property) 提供引用值;或者使特定行為能夠符合必須用屬性 (Property) 類型值填充 XAML 屬性 (Property) 這一常規(guī)行為要求。
例如,下面的示例使用屬性 (Attribute) 語(yǔ)法設(shè)置 Style 屬性 (Property) 的值。Style 屬性 (Property) 采用了 Style 類的一個(gè)實(shí)例,這是默認(rèn)情況下不能在屬性 (Attribute) 語(yǔ)法字符串中指定的引用類型。但在本例中,屬性 (Attribute) 引用了特定的標(biāo)記擴(kuò)展 StaticResource。當(dāng)處理該標(biāo)記擴(kuò)展時(shí),它返回對(duì)以前在資源字典中作為鍵控資源進(jìn)行實(shí)例化的某個(gè)樣式的引用。
資源只是 WPF 或 XAML 啟用的一種標(biāo)記擴(kuò)展用法。
支持 Typeconverter 的屬性值
在“屬性語(yǔ)法”一節(jié)中,曾提到屬性值必須能夠使用字符串進(jìn)行設(shè)置。對(duì)字符串如何轉(zhuǎn)換為其他對(duì)象類型或基元值的基本本機(jī)處理取決于 String 類型本身。但是很多 WPF 類型或這些類型的成員擴(kuò)展了基本字符串屬性處理行為,因此更復(fù)雜的對(duì)象類型的實(shí)例可通過(guò)字符串指定為屬性值。在代碼級(jí)別,此處理是通過(guò)指定處理字符串屬性值的 CLR 類型轉(zhuǎn)換器來(lái)完成的。常用于指示矩形區(qū)域尺寸(如 Margin)的 Thickness 結(jié)構(gòu)類型是這樣一個(gè)類型的示例:它具有針對(duì)采用該類型的所有屬性 (Property) 公開的一個(gè)特殊的、支持類型轉(zhuǎn)換器的屬性 (Attribute) 語(yǔ)法,以便于在 XAML 標(biāo)記中使用。下面的示例使用支持類型轉(zhuǎn)換器的屬性 (Attribute) 語(yǔ)法來(lái)為 Margin 提供值:
上面的屬性 (Attribute) 語(yǔ)法示例與下面更為詳細(xì)的語(yǔ)法示例等效,但在下面的示例中,Margin 是通過(guò)包含 Thickness 對(duì)象元素的屬性 (Property) 元素語(yǔ)法設(shè)置的,而且 Thickness 的四個(gè)關(guān)鍵屬性 (Property) 設(shè)置為新實(shí)例的屬性 (Attribute):
是使用支持類型轉(zhuǎn)換器的語(yǔ)法,還是使用更詳細(xì)的等效語(yǔ)法,通常只是編碼風(fēng)格的選擇問(wèn)題,但支持轉(zhuǎn)換器的語(yǔ)法有助于生成更簡(jiǎn)潔的標(biāo)記。(但是,有一些對(duì)象只能采用類型轉(zhuǎn)換器將屬性設(shè)置為該類型,因?yàn)轭愋蛯?duì)象本身并沒(méi)有默認(rèn)的構(gòu)造函數(shù)。例如,Cursor。)
集合類型和 XAML 集合屬性 XAML 指定了一個(gè)語(yǔ)言功能,通過(guò)該功能,可以從標(biāo)記中特意省略表示集合類型的對(duì)象元素。當(dāng) XAML 處理器處理采用了集合類型的屬性時(shí),將隱式創(chuàng)建相應(yīng)集合類型的實(shí)例,即使標(biāo)記中不存在該集合的對(duì)象元素也是如此。在集合類型的 SDK 參考頁(yè)中,特意省略集合對(duì)象元素的這種語(yǔ)法在 XAML 語(yǔ)法部分中有時(shí)候稱為“隱式集合語(yǔ)法”。
隱式集合語(yǔ)法適用于實(shí)現(xiàn) IList 或 IDictionary 的類型,或者適用于數(shù)組。
您已經(jīng)在 XAML 資源示例中看到了未調(diào)用的集合對(duì)象元素的隱式集合語(yǔ)法的示例:
除了根元素外,頁(yè)面上作為另一個(gè)元素的子元素而嵌套的每個(gè)對(duì)象元素實(shí)際上都是下列一種或兩種情況下的元素:父元素的隱式集合屬性的一個(gè)成員,或者為父元素指定 XAML 內(nèi)容屬性值的元素(XAML 內(nèi)容屬性將在下一節(jié)進(jìn)行討論)。換言之,一個(gè)標(biāo)記頁(yè)上的父元素與子元素之間的關(guān)系實(shí)際上就是一個(gè)根對(duì)象,而根對(duì)象下面的每個(gè)對(duì)象元素要么是為父元素提供屬性值的一個(gè)實(shí)例,要么是同樣作為父元素的集合類型屬性值的集合中的一項(xiàng)。在資源示例的案例中,Resources 屬性采用 ResourceDictionary 類型的一個(gè)對(duì)象。下面的示例在語(yǔ)法上與顯式指定的 ResourceDictionary 的對(duì)象元素等效。
Resources 集合是許多常見的 WPF 框架級(jí)元素上存在的集合屬性的一個(gè)示例。在 XAML 中設(shè)置此屬性需要使用屬性元素語(yǔ)法。屬性元素中的每個(gè)被包含的對(duì)象元素都成為集合(IDictionary 實(shí)現(xiàn))中的一個(gè)項(xiàng)。雖然集合類型本身通常沒(méi)有包含項(xiàng)的屬性或索引器,但是該屬性不能在標(biāo)記中指定;它完全是隱含的。對(duì)于 ResourceDictionary,該屬性是 Item 索引器。
XAML 內(nèi)容屬性 XAML 指定了一個(gè)語(yǔ)言功能,通過(guò)該功能,任何可以用作 XAML 對(duì)象元素的類都可以確切指定其屬性之一作為該類實(shí)例的 XAML 內(nèi)容屬性。當(dāng) XAML 處理器處理具有 XAML 內(nèi)容屬性的對(duì)象元素時(shí),該對(duì)象元素的任何 XML 子元素都被當(dāng)作包含在一個(gè)表示該內(nèi)容屬性的隱式屬性元素標(biāo)記中來(lái)處理。在標(biāo)記中,可以省略 XAML 內(nèi)容屬性的屬性元素語(yǔ)法。在標(biāo)記中指定的任何子元素都將成為 XAML 內(nèi)容屬性的值。
您已經(jīng)看過(guò)了未調(diào)用的 XAML 內(nèi)容屬性的示例:本主題中的第一個(gè)示例。
這里,Button 是 StackPanel 的子元素。這是一個(gè)簡(jiǎn)單直觀的標(biāo)記,其中出于兩個(gè)不同的原因省略了兩個(gè)標(biāo)記。
省略的 StackPanel.Children 屬性元素: StackPanel 從 Panel 派生。Panel 將 Panel..::.Children 定義為其 XAML 內(nèi)容屬性。Panel 的所有派生類因而具有該 XAML 內(nèi)容屬性,而 Panel..::.Children 的屬性元素可省略。
省略的 UIElementCollection 對(duì)象元素: Panel..::.Children 屬性采用類型 UIElementCollection,該類型實(shí)現(xiàn) IList。因此,根據(jù)為集合定義的 XAML 規(guī)則,可以省略 UIElementCollection 對(duì)象元素標(biāo)記。在這種情況下,UIElementCollection 實(shí)際上不能實(shí)例化為一個(gè)對(duì)象元素。您甚至無(wú)法顯式聲明該集合對(duì)象。這是因?yàn)?UIElementCollection 不公開默認(rèn)的構(gòu)造函數(shù)。其他幾個(gè) WPF 集合類型也不公開對(duì)象元素用法的構(gòu)造函數(shù),因?yàn)?XAML 集合語(yǔ)法處理仍然允許它們?cè)?XAML 中隱式工作。這就是 UIElementCollection 對(duì)象元素在示例中顯示為已被注釋的原因;如果未被注釋,示例將不能編譯。
內(nèi)部文本和 XAML 內(nèi)容屬性 StackPanel / Button 示例還有另一種變體。
請(qǐng)注意為 Button 指定的顯示文本如何發(fā)生變化。前面已在屬性 (Attribute) 語(yǔ)法中指定了 Content 屬性 (Property);這次顯示字符串是 Button 對(duì)象元素中的內(nèi)部文本。此語(yǔ)法可行,因?yàn)?Content 是 Button 基類 ContentControl 的 XAML 內(nèi)容屬性。元素中的字符串根據(jù) Content 屬性的屬性類型(即 Object)進(jìn)行計(jì)算。Object 不會(huì)嘗試任何字符串類型轉(zhuǎn)換,因此 Content 屬性的值變成了文本字符串值。或者,Button 中的內(nèi)容可以是任何單個(gè) Object。Button 等控件通常為類定義 XAML 內(nèi)容屬性,因此 XAML 內(nèi)容屬性可用于 UI 和顯示文本,或用于控件合成,或同時(shí)用于此兩者。
對(duì)于流程文檔模型和本地化而言,在元素中放置字符串作為內(nèi)容以生成與其他常見標(biāo)記語(yǔ)言類似的標(biāo)記的功能特別重要。
XAML 內(nèi)容屬性值必須連續(xù) XAML 內(nèi)容屬性的值必須完全在該對(duì)象元素的其他任何屬性元素之前或之后指定。不管 XAML 內(nèi)容屬性的值指定為字符串還是指定為一個(gè)或多個(gè)對(duì)象都是如此。例如,下面的標(biāo)記無(wú)法進(jìn)行編譯:
這在本質(zhì)上是非法的,因?yàn)槿绻苏Z(yǔ)法是通過(guò)使用內(nèi)容屬性的屬性元素語(yǔ)法而變?yōu)轱@式的,則內(nèi)容屬性將設(shè)置兩次:
一個(gè)類似的非法示例是,如果內(nèi)容屬性是一個(gè)集合,則子元素是與屬性元素交錯(cuò)的:
內(nèi)容模型 從語(yǔ)法上講,可能支持將類用作 XAML 元素,但只有放置到整體內(nèi)容模型或元素樹中的所需位置時(shí),該元素才能在應(yīng)用程序或頁(yè)面上正常運(yùn)行。例如,MenuItem 通常只應(yīng)作為 MenuBase 派生類(如 Menu)的子級(jí)放置。特定元素的內(nèi)容模型在可用作 XAML 元素的控件和其他 WPF 類的類頁(yè)面上的備注中進(jìn)行說(shuō)明。對(duì)于具有更復(fù)雜內(nèi)容模型的某些控件,內(nèi)容模型作為單獨(dú)的概念主題進(jìn)行說(shuō)明。
XAML 中的大小寫和空白 XAML 區(qū)分大小寫。按名稱與程序集中的基礎(chǔ)類型進(jìn)行比較或者與類型的成員進(jìn)行比較時(shí),必須使用正確的大小寫指定所有對(duì)象元素、屬性 (Property) 元素和屬性 (Attribute) 名稱。屬性的值并不總是區(qū)分大小寫。值是否區(qū)分大小寫將取決于與采用該值的屬性關(guān)聯(lián)的類型轉(zhuǎn)換器行為,或取決于屬性值類型。例如,采用 Boolean 類型的屬性可以采用 true 或 True 作為等效值,但只是因?yàn)?Boolean 的默認(rèn)字符串類型轉(zhuǎn)換已經(jīng)允許這些值作為等效值。
XAML 處理器和序列化程序?qū)⒑雎曰騽h除所有無(wú)意義的空白,并規(guī)范化任何有意義的空白。只有當(dāng)您在 XAML 內(nèi)容屬性中指定字符串時(shí),才會(huì)體現(xiàn)此行為的重要性。簡(jiǎn)言之,XAML 將空格、換行符和制表符轉(zhuǎn)化為空格,如果它們出現(xiàn)在一個(gè)連續(xù)字符串的任一端,則保留一個(gè)空格。
有關(guān) XAML 語(yǔ)法的更多信息 隱式集合語(yǔ)法和 XAML 內(nèi)容屬性都是允許省略某些推斷標(biāo)記的 XAML 語(yǔ)言功能。這些功能的目的是在編寫或檢查標(biāo)記時(shí)使頁(yè)面上的元素的父子關(guān)系更明顯。
如果您正在創(chuàng)建自定義類,并且正在考慮是否允許使用 XAML,XAML 語(yǔ)法術(shù)語(yǔ)主題也是一個(gè)很好的起點(diǎn)。
XAML 根元素和 xmlns 一個(gè) XAML 文件只能有一個(gè)根元素,這樣才能成為格式正確的 XML 文件和有效的 XAML 文件。通常,應(yīng)選擇屬于應(yīng)用程序模型一部分的元素(例如,為頁(yè)面選擇 Window 或 Page,為外部字典選擇 ResourceDictionary,或?yàn)閼?yīng)用程序定義根選擇 Application)。下面的示例演示 WPF 頁(yè)面的典型 XAML 文件的根元素,其中的根元素為 Page。
根元素還包含屬性 xmlns 和 xmlns:x。這些屬性向 XAML 處理器指明哪些命名空間包含標(biāo)記將要引用的元素的元素定義。xmlns 屬性專門指示默認(rèn)的 xmlns 命名空間。在默認(rèn)的 xmlns 命名空間中,可以不使用前綴指定標(biāo)記中的對(duì)象元素。對(duì)于大多數(shù) WPF 應(yīng)用程序方案以及 SDK 的 WPF 部分中給出的幾乎所有示例,默認(rèn)的 xmlns 命名空間均映射為 WPF 命名空間 http://schemas.microsoft.com/winfx/2006/xaml/presentation。xmlns:x 屬性指示另外一個(gè) xmlns 命名空間,該命名空間映射 XAML 語(yǔ)言命名空間 http://schemas.microsoft.com/winfx/2006/xaml。在具有此映射的文件的標(biāo)記中引用時(shí),XAML 規(guī)范定義的必需語(yǔ)言組件帶有 x: 前綴。使用 xmlns 定義用法范圍和映射的這種做法符合 XML 1.0 規(guī)范。請(qǐng)注意,xmlns 屬性僅在每頁(yè)的根元素上和應(yīng)用程序定義上(如果在標(biāo)記中提供了應(yīng)用程序定義)才是嚴(yán)格必需的。xmlns 定義將應(yīng)用于根的所有子元素。(此行為仍然符合 xmlns 的 XML 1.0 規(guī)范。)xmlns 屬性還允許出現(xiàn)在根下面的其他元素上,并且將應(yīng)用于定義元素的任何子元素。但是,此用法并不典型,因?yàn)轭l繁定義或重新定義 xmlns 命名空間可能會(huì)導(dǎo)致 XAML 標(biāo)記樣式難以閱讀。
由于存在屬于項(xiàng)目生成文件一部分的配置,因此可以知道 WPF 程序集包含的某些類型支持 WPF 到默認(rèn) xmlns 的映射。程序集還映射到目標(biāo)文件中。因此,為了引用來(lái)自 WPF 程序集的 XAML 元素,只需映射 xmlns 即可。對(duì)于您自己的自定義程序集,或者除 WPF 之外的程序集,可以將該程序集指定為 xmlns 映射的一部分。通常,可選擇其他前綴,但是也可以選擇其他 xmlns 作為默認(rèn)值,然后將 WPF 映射到前綴。
x: 前綴 在前面的根元素示例中,前綴 x: 用于映射 XAML xmlns http://schemas.microsoft.com/winfx/2006/xaml。在此 SDK 的項(xiàng)目模板、示例以及文檔中,此 x: 前綴將用于映射 XAML xmlns。x: 前綴/XAML xmlns 包含多個(gè)將在 XAML 中頻繁用到的編程構(gòu)造。下面列出了將用到的最常見 x: 前綴/XAML xmlns 編程構(gòu)造:
x:Key:為 ResourceDictionary 中的每個(gè)資源設(shè)置一個(gè)唯一的鍵。在應(yīng)用程序標(biāo)記中看到的所有 x: 用法中,x:Key 可能占到 90%。
x:Class:向?yàn)?XAML 頁(yè)提供代碼隱藏的類指定 CLR 命名空間和類名。必須具有這樣一個(gè)類才能支持代碼隱藏,也正是由于這個(gè)原因,即使沒(méi)有資源,您也幾乎總是會(huì)看到映射的 x:。
x:Name:處理對(duì)象元素后,為運(yùn)行時(shí)代碼中存在的實(shí)例指定運(yùn)行時(shí)對(duì)象名稱。在不支持等效的 WPF 框架級(jí)Name 屬性的情況下命名元素時(shí),可以使用 x:Name。某些動(dòng)畫方案中會(huì)發(fā)生這種情況。
x:Static:啟用一個(gè)獲取靜態(tài)值的值引用,該靜態(tài)值只能是一個(gè) XAML 可設(shè)置屬性。
x:Type:根據(jù)類型名稱構(gòu)造一個(gè) Type 引用。它用于指定采用 Type 的屬性 (Attribute),如 Style..::.TargetType,不過(guò)在許多情況下屬性 (Property) 本身具有字符串到 Type 的轉(zhuǎn)換功能,因此使用 x:Type 是可選的。
x: 前綴/XAML xmlns 中還有其他一些不太常見的編程構(gòu)造。 事件和 XAML 代碼隱藏 大多數(shù) WPF 應(yīng)用程序都是既包括標(biāo)記,又包括代碼隱藏。在一個(gè)項(xiàng)目中,XAML 被編寫為 .xaml 文件,而使用 CLR 語(yǔ)言(如 Microsoft Visual Basic .NET 或 C#)編寫代碼隱藏文件。編譯 XAML 文件時(shí),每個(gè) XAML 頁(yè)的 XAML 代碼隱藏文件的位置是通過(guò)指定一個(gè)命名空間和類作為 XAML 頁(yè)的根元素的 x:Class 屬性來(lái)確定的。
在目前已介紹的示例中,您已看到幾個(gè)按鈕,但還沒(méi)有一個(gè)按鈕具有任何關(guān)聯(lián)的邏輯行為。為對(duì)象元素添加行為的主要應(yīng)用程序級(jí)機(jī)制是使用元素類的現(xiàn)有事件,并為在運(yùn)行時(shí)引發(fā)該事件時(shí)調(diào)用的該事件編寫特定的處理程序。事件名稱以及要使用的處理程序的名稱在標(biāo)記中指定,而實(shí)現(xiàn)處理程序的代碼在代碼隱藏中定義。
請(qǐng)注意,代碼隱藏文件使用命名空間 MyNamespace 并將 MyPageCode 聲明為該命名空間內(nèi)的一個(gè)分部類。這相當(dāng)于在標(biāo)記根中提供的 MyNamespace.MyPageCode 的 x:Class 屬性值。編譯器將通過(guò)從根元素類型派生一個(gè)類,自動(dòng)為編譯的任何 XAML 頁(yè)創(chuàng)建一個(gè)分部類。當(dāng)您提供也會(huì)定義同一分部類的代碼隱藏時(shí),將在與編譯的應(yīng)用程序相同的命名空間和類中組合生成的代碼。
如果您不想創(chuàng)建單獨(dú)的代碼隱藏文件,還可以將代碼內(nèi)聯(lián)到 XAML 文件中。但是,內(nèi)聯(lián)代碼是一種缺少多樣性的方法,有很多的限制。
事件屬性語(yǔ)法 當(dāng)您在標(biāo)記中通過(guò)事件指定行為時(shí),通常使用屬性語(yǔ)法來(lái)附加處理程序。在其中指定事件屬性的對(duì)象元素則變成偵聽事件以及調(diào)用處理程序的實(shí)例。您要處理的具體事件的名稱是屬性名。屬性值是您要定義的處理程序的方法名。然后您必須在代碼隱藏中提供處理程序?qū)崿F(xiàn),并使處理程序基于該事件的委托。您使用編程語(yǔ)言(如 Microsoft Visual Basic .NET 或 C#)在代碼隱藏中編寫處理程序。
引發(fā)事件時(shí),每個(gè) WPF 事件都將報(bào)告事件數(shù)據(jù)。事件處理程序可以訪問(wèn)這些事件數(shù)據(jù)。在前面的示例中,處理程序通過(guò)事件數(shù)據(jù)獲取所報(bào)告的事件源,然后在該事件源上設(shè)置屬性。
路由事件 路由事件是一個(gè)特殊的事件功能,該功能是 WPF 特有的并且是它的基礎(chǔ)。路由事件允許一個(gè)元素處理另一個(gè)元素引發(fā)的事件,只要這些元素通過(guò)元素樹關(guān)系連接起來(lái)。當(dāng)使用 XAML 屬性指定事件處理時(shí),可以在任何元素(包括未在類成員表中列出該特定事件的元素)上偵聽和處理路由事件。這是通過(guò)使用所屬類名限定事件名屬性來(lái)實(shí)現(xiàn)的。例如,在當(dāng)前所討論的 StackPanel / Button 示例中,父 StackPanel 可以通過(guò)在 StackPanel 對(duì)象元素上指定屬性 Button.Click,并使用處理程序名作為屬性值,為子元素按鈕的 Click 事件注冊(cè)一個(gè)處理程序。
x:Name
默認(rèn)情況下,通過(guò)處理對(duì)象元素而創(chuàng)建的對(duì)象實(shí)例沒(méi)有可供您在代碼中使用的唯一標(biāo)識(shí)符或固有的對(duì)象引用。當(dāng)您在代碼中調(diào)用構(gòu)造函數(shù)時(shí),幾乎總是使用構(gòu)造函數(shù)結(jié)果為構(gòu)造的實(shí)例設(shè)置一個(gè)變量,以便以后在代碼中引用該實(shí)例。為了對(duì)通過(guò)標(biāo)記定義創(chuàng)建的對(duì)象進(jìn)行標(biāo)準(zhǔn)化訪問(wèn),XAML 定義了 x:Name 屬性。您可以在任何對(duì)象元素上設(shè)置 x:Name 屬性的值。在代碼隱藏文件中,您選擇的標(biāo)識(shí)符等效于引用所構(gòu)造的實(shí)例的實(shí)例變量。在任何方面,命名元素都像它們是對(duì)象實(shí)例一樣工作(此名稱只是引用該實(shí)例),并且代碼隱藏文件可以引用該命名元素來(lái)處理應(yīng)用程序內(nèi)的運(yùn)行時(shí)交互。
WPF 框架級(jí) XAML 元素繼承 Name 屬性 (Property),該屬性等效于 XAML 定義的 x:Name 屬性 (Attribute)。其他某些類也為 x:Name(通常也定義為 Name 屬性)提供屬性級(jí)等效項(xiàng)。一般而言,如果您在所選元素的成員表中找不到 Name 屬性,可以改用 x:Name。
下面的示例在 StackPanel 元素上設(shè)置 Name。然后,該 StackPanel 中的 Button 上的處理程序通過(guò)由 Name 設(shè)置的實(shí)例引用 buttonContainer 來(lái)引用 StackPanel。
就像變量一樣,實(shí)例的名稱受范圍概念的控制,因此可以在可預(yù)測(cè)的某個(gè)范圍內(nèi)強(qiáng)制名稱唯一。定義頁(yè)面的主要標(biāo)記表示一個(gè)唯一的名稱范圍,而該名稱范圍的邊界就是該頁(yè)面的根元素。但是,其他標(biāo)記源(如樣式或樣式中的模板)可以在運(yùn)行時(shí)與頁(yè)面交互,這種標(biāo)記源常常具有其自己的名稱范圍,這些名稱范圍不一定與頁(yè)面的名稱范圍相連接。
附加屬性和附加事件 XAML 指定了一個(gè)語(yǔ)言功能,該功能允許在任何元素上指定某些屬性或事件,而不管要為其設(shè)置屬性或事件的元素的成員表中是否存在該屬性或元素。該功能的屬性版本稱為附加屬性,事件版本稱為附加事件。從概念上講,您可以將附加屬性和附加事件認(rèn)為是可以在任何元素/類上設(shè)置的全局成員,而不管其類層次結(jié)構(gòu)如何。
通常通過(guò)屬性 (Attribute) 語(yǔ)法來(lái)使用 XAML 中的附加屬性 (Property)。在屬性 (Attribute) 語(yǔ)法中,您可以按照所有者類型.屬性名 的形式指定附加屬性 (Property)。表面上,這與屬性元素用法類似,但在這種情況下,您指定的所有者類型 始終是一種與要為其設(shè)置附加屬性的對(duì)象元素不同的類型。所有者類型 這種類型提供 XAML 處理器獲取或設(shè)置附加屬性值所需要的訪問(wèn)器方法。使用附加屬性的最常見方案是使子元素能夠向其父元素報(bào)告屬性值。
下面的示例演示了 DockPanel..::.Dock 附加屬性。DockPanel 類為 DockPanel..::.Dock 定義訪問(wèn)器,因此擁有附加屬性。DockPanel 類還包括一個(gè)邏輯,該邏輯迭代其子元素并具體檢查每個(gè)元素是否具有 DockPanel..::.Dock 設(shè)置值。如果找到一個(gè)值,將在布局過(guò)程中使用該值定位子元素。使用 DockPanel..::.Dock 附加屬性和這種定位功能事實(shí)上是 DockPanel 類的激動(dòng)人心的一面。
在 Windows Presentation Foundation (WPF) 中,所有附加屬性還作為依賴項(xiàng)屬性來(lái)實(shí)現(xiàn)。
附加事件使用類似的所有者類型.事件名 屬性語(yǔ)法形式。就像非附加事件一樣,XAML 中的附加事件的屬性值指定在元素上處理事件時(shí)調(diào)用的處理程序方法的名稱。
使用附加事件的一種方案適用于可在任何元素(如鼠標(biāo)按鈕)上處理的設(shè)備輸入事件。例如,Mouse..::.MouseDown 就是這樣一個(gè)附加事件。但是,大多數(shù) WPF 框架級(jí)元素可以使用此事件,而無(wú)需使用附加事件。這是因?yàn)榛仡?UIElement 可為 Mouse..::.MouseDown 附加事件創(chuàng)建一個(gè)別名,并在 UIElement 成員表中公開該別名(為 MouseDown)。因此,通常不需要在 XAML 頁(yè)或 Windows Presentation Foundation (WPF) 應(yīng)用程序編程中指定附加事件語(yǔ)法。例外情況包括,您使用的是自定義元素,或者使用并非從 UIElement 派生但仍然具有可視化表示形式的對(duì)象元素(這些情況很少見)。在 WPF 中,所有附加事件還作為路由事件來(lái)實(shí)現(xiàn)。ContentElement 也為輸入事件公開別名,供流程文檔模型使用。
XAML 頁(yè)面根元素剖析 下表顯示了一個(gè)典型的 XAML 頁(yè)面根元素分解結(jié)構(gòu),并顯示了本主題中介紹的根元素的具體屬性:
基類和 XAML 基礎(chǔ) XAML 及其架構(gòu)是一個(gè)類集合,這些類對(duì)應(yīng)于 CLR 對(duì)象以及要在 XAML 中使用的標(biāo)記元素。但是,并不是所有的類都能映射到元素。抽象類(如 ButtonBase)和某些非抽象基類在 CLR 對(duì)象模型中用于繼承,并且不支持對(duì)應(yīng)的 XAML 標(biāo)記。基類(包括抽象類)對(duì)于 XAML 開發(fā)仍然很重要,因?yàn)槊總€(gè)具體的 XAML 元素都從其層次結(jié)構(gòu)中的某個(gè)基類繼承成員。通常,這些成員包括可以設(shè)置為元素屬性 (Attribute) 的屬性 (Property),或者可以處理的事件。FrameworkElement 是 WPF 在 WPF 框架級(jí)的具體 UI 基類。設(shè)計(jì) UI 時(shí),您將使用各種形狀、面板、修飾器或控件類,它們?nèi)繌?FrameworkElement 派生而來(lái)。有一個(gè)相關(guān)的基類 FrameworkContentElement,它使用可在 FrameworkElement 中特意鏡像 API 的 API,支持適合流布局表示形式的面向文檔的元素。元素級(jí)的屬性 (Attribute) 和 CLR 對(duì)象模型的組合提供了一組通用的屬性 (Property),可以在大多數(shù)具體的 XAML 元素上設(shè)置這些屬性 (Property),而不管確切的元素類型及其基礎(chǔ)類是什么。
XAML 安全性 XAML 是一種直接表示對(duì)象實(shí)例化和執(zhí)行的標(biāo)記語(yǔ)言。因此,使用 XAML 創(chuàng)建的元素能夠像等效的生成代碼那樣與系統(tǒng)資源進(jìn)行交互(如網(wǎng)絡(luò)訪問(wèn)、文件系統(tǒng) IO)。
WPF 支持 .NET 安全框架代碼訪問(wèn)安全性 (CAS)。這意味著在 Internet 區(qū)域中運(yùn)行的 WPF 內(nèi)容具有更少的執(zhí)行權(quán)限。“松散 XAML”(由 XAML 查看器在加載時(shí)解釋的未編譯 XAML 的頁(yè)面)和 XAML 瀏覽器應(yīng)用程序 (XBAP) 通常在此 Internet 區(qū)域中運(yùn)行,并且使用相同的權(quán)限集。但是,加載到完全受信任的應(yīng)用程序中的 XAML 與宿主應(yīng)用程序具有相同的系統(tǒng)資源訪問(wèn)權(quán)限。有關(guān)更多信息,請(qǐng)參見 Windows Presentation Foundation 部分信任安全性。
從代碼中加載 XAML XAML 可用于定義整個(gè) UI,但有時(shí)也適合只使用 XAML 定義 UI 的一部分。利用此功能可以實(shí)現(xiàn)部分自定義、在本地存儲(chǔ)信息、使用 XAML 提供業(yè)務(wù)對(duì)象或者各種可能的方案。這些方案的關(guān)鍵是 XamlReader 類及其 Load 方法。輸入是一個(gè) XAML 文件,而輸出是一個(gè)對(duì)象,它表示從該標(biāo)記中創(chuàng)建的對(duì)象的整個(gè)運(yùn)行時(shí)樹。然后您可以插入該對(duì)象,作為應(yīng)用程序中已存在的另一個(gè)對(duì)象的屬性。只要該屬性在具有最終顯示功能并且將通知執(zhí)行引擎已在應(yīng)用程序中添加新內(nèi)容的內(nèi)容模型中是一個(gè)合適的屬性,您就可以通過(guò)以 XAML 形式加載來(lái)輕松地修改正在運(yùn)行的應(yīng)用程序的內(nèi)容。請(qǐng)注意,通常只在完全受信任的應(yīng)用程序中使用此功能,因?yàn)閷⑽募虞d到正在運(yùn)行的應(yīng)用程序中會(huì)帶來(lái)明顯的安全隱患。
接下來(lái)的內(nèi)容 本主題簡(jiǎn)單介紹了 XAML 語(yǔ)法概念和術(shù)語(yǔ)。
如果您尚未了解這些內(nèi)容,請(qǐng)嘗試閱讀 Windows Presentation Foundation 入門教程。當(dāng)您真正創(chuàng)建本教程中介紹的標(biāo)記應(yīng)用程序時(shí),其中的練習(xí)將幫助您進(jìn)一步了解本主題中介紹的許多概念。
WPF 使用一個(gè)特定的應(yīng)用程序模型,該模型基于 Application 類。
生成 WPF 應(yīng)用程序 (WPF) 為您詳細(xì)介紹了如何通過(guò)命令行以及使用 Microsoft Visual Studio 生成包含 XAML 的應(yīng)用程序。
依賴項(xiàng)屬性概述詳細(xì)介紹了 Windows Presentation Foundation (WPF) 中屬性的多樣性,并介紹了依賴項(xiàng)屬性的概念。
最后,SDK 中還包含一個(gè)稱為 XAMLPad 的 XAML 編輯工具。您可以使用此工具實(shí)時(shí)體驗(yàn) XAML。
?摘自:http://developer.51cto.com/art/200808/87148.htm
轉(zhuǎn)載于:https://www.cnblogs.com/h20064528/archive/2012/09/27/2706299.html
總結(jié)
以上是生活随笔為你收集整理的WPF基础之XAML的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 企业真的要培养员工?
- 下一篇: ACS AD 和本地验证SSL ×××