原文地址:web
系列地址:http://channel9.msdn.com/Series/Windows-Phone-8-Development-for-Absolute-Beginners編輯器
源代碼: http://aka.ms/absbeginnerdevwp8
PDF版本: http://aka.ms/absbeginnerdevwp8pdf函數
在本課中,我將討論在第一課中編寫的SoudBoard應用程序的XAML語法。但願您注意到了咱們編寫的XAML是如何影響手機預覽窗格中咱們見到的內容。經過查看XAML來理解絕對基本的XAML是相對簡單的,可是我想指出一些並不是一眼就能看出的特性和功能。佈局
概要地講本課的計劃是:學習
個人目標是:當本課結束時您將具有足夠的理解咱們在本系列其他部分編寫的XAML的知識,而且在我試圖解釋前就可以基本猜出它的做用。spa
在上一課我提到XAML的外觀與HTML相似。這並不是偶然。XAML其實就是XML(可擴展標記語言the eXtensible Markup Language)。我待會兒會解釋它們的關係,可是概要地講,XML和HTML很是類似,它們具備共同的祖先。HTML用於構建web頁面文檔,而XML則更通用。此處「通用」的意思是您能夠針對設想的任意用途來使用它,而且您能夠定義元素和特性(attributes)的名稱來知足您的須要。過去開發者利用XML來存儲應用設置,在兩個不一樣的系統之間傳輸數據。爲了使用XML,您須要定義架構(schema),它對元素和元素特性的名稱進行聲明。架構相似於一個合約(contract)。每一個人,無論他是XML的生產者仍是XML的使用者都遵照合約的規定以在相互間進行通信。所以架構是XML的重要組成部分。請記住上述分析,待會兒咱們還會對他進行討論。設計
XAML是XML的一種特殊用法。很顯然,咱們已經看到XAML與定義手機的用戶界面有關。因此在這點上感受它很是像HTML。可是有一個很大的區別,XAML實際上用於建立類的實例和設置屬性(properties)的值。例如,在前面的課程中咱們在XAML中定義了一個按鈕:3d
上述代碼大體等同於如下的C#代碼:code
我已將上述C#代碼添加到MainPage類的構造函數中。我待會兒會討論MainPage.xaml和MainPage.xaml.cs之間的關係,可是咱們已經看到如何在MainPage.xaml.cs中經過編寫程序方式的C#代碼來定義行爲。這裏我僅僅編寫了在MainPage類的新實例被建立時執行的代碼(經過在類的構造函數中編寫代碼來實現)。
如今我有了兩個按鈕,一個以聲明方式在XAML中定義、含有「內容Hello World」而且在單擊按鈕時會發出嘎嘎的叫聲,另外一個是新建立的含有內容「Quack」 的按鈕。當咱們運行應用:
咱們僅能看見一個按鈕。那是由於我剛在C#中以程序方式(在MainPage類的構造函數中)建立的按鈕位於咱們在上一課中在XAML中建立的按鈕之上。我將加入一行C#代碼用於設置新的Quack按鈕的邊距(margin),將它移動到靠左210像素的位置。
按鈕的邊距(Margin)屬性是Thickness類型,它是一個通用用途的表明4個維度的類。在這裏咱們建立了一個新的Thickness類並設置它的構造函數的第一個參數爲210像素。當咱們再次運行應用:
咱們如今能夠看到兩個按鈕。
更大的問題是咱們有了兩個(幾乎)相同的按鈕,一個以聲明方式在XAML中建立,另外一個以程序方式在C#中建立。
當我這樣建立一個新的XAML元素時:
<Button></Button>
我基本上是在建立了一個新的按鈕類的實例。
當我設置按鈕元素的特性時,我基本上在設置按鈕類實例的屬性。
重要的是:XAML是建立類的實例和設置對象屬性的一種更加簡化和簡潔的語法。用10行C#代碼才能完成的工做只須要一行XAML。(即便在編輯器中我將它分紅數行,它仍然比用C#建立對象的方法要簡短得多)
此外,使用XAML我能夠在手機預覽窗格中迅速得到反饋。我當即能夠看到更改的影響。在編寫程序方式的C#代碼時,當須要觀察對代碼的改動如何工做時我須要運行應用程序。
若是您有敏銳的眼光,當遇到HorizontalAlignment特性時,您可能已經注意到XAML和C#版本的差別。若是您嘗試:
myButton.HorizontalAlignment = 「Left」;
將會產生一個編譯錯誤。XAML分析器將經過值轉換器來執行字符串「Left」到枚舉值System.Windows.HorizontalAlignment.Left的轉換。類型轉換器是一個類,它能夠將字符串值轉換爲強類型,Windows 8 API中有若干類型轉換器,咱們會在這個系列中一直使用它們。在本例中的HorizontalAlignment屬性,當被微軟的開發人員開發時,在源代碼中被一個特殊的特性標記,它指示XAML分析器經過類型轉換器方法嘗試將字符串「Left」匹配爲枚舉值System.Windows.HorizontalAlignment.Left。
當您試圖拼錯「Left」時,看看會發生什麼:
您將會收到一個編譯錯誤,由於類型轉換器不能找到一個準確的匹配以轉換爲枚舉值System.Windows.HorizontalAlignment.Left。
所以,XAML的第一個特色是:它是一種簡潔的建立類的實例的手段。在構建Windows 8應用時,它被用來建立用戶界面元素的實例,可是XAML不只僅是一項用戶界面技術,它能夠在其餘技術中用於其餘目的。
接下來,讓咱們討論MainPage.xaml文件頂部的代碼,咱們在以前一直沒有涉及到它。
在文件頂部咱們看到如下內容:
當您在查看上述內容時,回憶一下我剛纔說的—有關架構屬於XML的一部分。若是確實如此,那麼XAML在哪裏保證遵照架構?
觀察第3行至第8行。MainPage.xaml須要保證遵照六個架構。每個都經過xmlns特性來定義。在第3行定義的第一個xmlns是缺省的命名空間,換句話說沒有冒號和冒號後的單詞,就像你在第4行至第8行看到的那樣。
第4行至第8行的其他命名空間使用名稱/冒號的組合。所以,須要說明的是:x 或:phone是與架構(咱們將其稱爲合約)相關的命名空間。MainPage.xaml其他部分的每一個元素或特性必須遵照至少這些架構中的一個,不然文檔就是無效的。換句話說,若是XAML中的元素或特性沒有在這些命名空間中定義,那麼就不能保證編譯器(即分析源代碼並建立可執行文件的程序)在手機上運行,編譯器將沒法理解如何執行特定的指令。
所以,在本例中:
<Grid x:Name="LayoutRoot" Background="Transparent">
咱們將指望Grid元素和Background特性是缺省架構的一部分,缺省架構對應第3行定義的缺省命名空間。
可是,x:Name是對應第4行定義的x:命名空間的架構的一部分。
我有一個好主意,讓咱們首先定位到缺省的命名空間以瞭解更多有關命名空間的構成:
http://schemas.microsoft.com/winfx/2006/xaml/presentation
什麼?!架構在該URL實際上並不存在!在這個意義上講,架構並無在該URL發佈並能夠查看。相反,架構只是一個惟一的名稱,相似於咱們在C#中使用命名空間識別兩個具備相同名稱的類。架構(所以,在XAML中的命名空間)使得類名稱能夠被排序,有點相似於姓氏和名字。該URL,或更恰當地說咱們應該認爲它是URI(Uniform Resource IDENTIFIER 統一資源標示符,而不是Locator 定位器),被用做命名空間的標示符。XML命名空間是對各種應用程序分析XAML的指令。Windows運行時XAML分析器將努力把它變成可執行代碼,而Visual Studio和Blend設計器將努力把它變成設計時的體驗。
所以,第二個XML命名空間定義了一個映射,x:屬於該架構。
http://schemas.microsoft.com/winfx/2006/xaml
所以,任何前面帶有x:前綴的元素或特性名稱意味着他們遵照第二個架構。
可是區別在哪裏?差異很小,可是第二個架構定義了XAML的內在規則。第一個架構定義了Windows 8對XAML特定使用方面的合約/規則。換句話說,咱們能夠不須要前綴而使用Grid, Button, MediaElement 和其餘Windows Phone 8 XAML元素的事實意味着他們定義於缺省的命名空間中。
第5和第6行爲Phone(手機)和Shell(界面)定義了命名空間和架構,他們位於不一樣的URI,注意Microsoft.Phone CLR(是Common Language Runtime的縮寫,即通用語言運行時)命名空間提供的線索,定義他們的程序集在安裝Windows Phone 8 API後被安裝在咱們的計算機上。
您能夠看到,第一行:
<phone:PhoneApplicationPage
代表PhoneApplicationPage類自己就是定義的一部分。PhoneApplicationPage從Windows.System.Controls.Page派生,它剛好也是Windows Presentation Foundation頁面類和Windows應用商店應用程序頁面類的父類。它含有不少被全部三種項目類型共享的基本功能。因此好處是您能夠利用在本系列中學到的內容建立WPF桌面應用和Windows應用商店應用。固然會有一些差別,可是也有不少共同點。
第7行和第8行定義用於容許Visual Studio左側的手機預覽窗格正常顯示的命名空間和架構。這些指令在運行時將被忽略,這也是第9行須要完成的工做—當編譯XAML代碼時,忽略任何爲:d的前綴。
好,我知道還有一些問題並未給出答案。咱們能夠花更多時間討論細節,可是重要的是在每一個添加到手機項目中的XAML文件頂部的代碼是有目的的,它定義了XAML代碼必須遵照的規則。您幾乎不須要修改這些代碼,可是若是您將它們刪除,您可能就會中斷您的應用程序。因此我以爲除非有充足的理由,不然不要改動它。在第10行至14行還有一些額外的內容,咱們將在本系列的之後課程中討論。
在Visual Studio的解決方案設計器中,您將看到XAML文件有一個箭頭,它意味着咱們能夠展開它們以顯示具備相同名稱的C#文件,惟一的區別是它在結尾處包含一個.cs的文件擴展名。若是查看.cs版本的文件,您將發現它定義了一個MainPage類,此外它定義了一個分部類(partial class):
另外一半在MainPage.xaml的第1和第2行中定義:
<phone:PhoneApplicationPage x:Class="SoundBoard.MainPage" ...
雖然他沒有使用Partial這一術語(不一樣於程序方式的對應部分),但他確實代表了兩者之間的關係。
爲何重要?這種關係意味着編譯器將把MainPage.xaml 和MainPage.xaml.cs的輸出合併到單個類中。這意味着他們是總體的兩個組成部分。這是一個重要的概念,XAML被編譯爲中間語言就像C#被編譯爲中間語言同樣而且他們都是單個類的部分實現。能夠這麼說,這使您能夠在一個文件中建立類的實例,而後在另外一個文件中使用它。這就是容許我在XAML中建立一個名稱爲_audioPlayer 的MediaElement類的實例而且在C#中調用它的方法和屬性的緣由。稍後咱們將在本課中看到更多這樣的例子。
由於XAML本質上是XML文檔,咱們能夠在其餘元素內嵌入元素。咱們已經看過這種狀況的一個例子。
<PhoneApplicationPage> <Grid ...> <Grid ... > <MediaElement ... /> <Button ... /> </Grid> </Grid> </PhoneApplicationPage>
或者,也許在XAML術語中更準確的說法是用戶控件(UserControl)的Content屬性被設置爲Grid,
這裏PhoneApplicationPage「包含」一個Grid,而且Grid「包含」一個MediaElement和一個Button。
而且Grid的子集合(Children collection)包括MediaElement 和Button。根據您正在使用的控件
類型,缺省屬性可使用嵌入樣式的語法被填充。因此您能夠這樣作:
<Button Content="Hello World" ... />
或者這樣
<Button ... > Hello World </Button>
由於Content屬性是Button類的缺省屬性。
在某些狀況下,僅僅設置特性值隱藏了後臺如何運做的複雜性。一個很好的例子就是設置Background=」Red」。在C#中咱們已經見過這個程序,它用於完成相同的事情:
myButton.Background = newSolidColorBrush(Colors.Red);
咱們須要建立一個新的SolidColorBrush實例並傳遞一個枚舉顏色值。這是另外一個很好的有關屬性類型轉換器的例子,咱們在較早前已經學習過了。可是有些特性太複雜以致於沒法表示爲特性。
當屬性(property)不可以簡單地表示爲XAML特性(attribute)時,它被稱爲「複雜屬性」。爲了演示它,首先我將從按鈕中刪除Background="Red"特性,刪除缺省屬性"Hello World!",並用特性Content="Quack"從新添加 :
接着,在屬性窗格我將Background屬性設置爲線性漸變畫筆。
我將在手機預覽窗格看到如下內容:
可是更重要的是:讓咱們查看畫筆編輯器生成的XAML。
用於建立背景的XAML不能簡單地像之前使用單詞」Red」那樣用一個簡單的字符串進行設置。相反,請注意Backgound屬性被轉變爲按鈕的自身元素:
<Button ... > <Button.Background> ... </Button.Background> </Button>
這被稱爲「屬性元素」語法,而且形式爲<Control.Property>。
一個很好的例子是線性漸變畫筆(LinearGradientBrush)。術語「畫筆 (Brush)」意味着咱們正在處理一個表示單個顏色(或多個顏色)的對象。將「畫筆」理解爲顏料刷,這個特殊的顏料刷將建立一個線性的漸變,顏色將從上到下或從左到右進行改變。固然,您實際上不會去作此處代碼所作的工做,由於它與Windows Phone 8應用程序的審美標準相悖。可是假設如今咱們須要經過使用漸變顏色做爲按鈕的背景顏色來表達咱們的個性。
您能夠看到(以下圖),若是咱們須要定義一個線性漸變畫筆,咱們須要提供不少信息以呈現正確的畫筆。例如何時應該進入下一個顏色。線性漸變畫筆包含一組GradientStop對象,它們定義了漸變中的顏色和顏色的位置。
然而,在上面的代碼段中表明LinearGradientBrush的XAML實際由Visual Studio自動進行了縮短。這是未縮短的格式:
<Button.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <LinearGradientBrush.GradientStops> <GradientStopCollection> <GradientStop Color="Red" Offset="1" /> <GradientStop Color="Black" Offset="0" /> </GradientStopCollection> </LinearGradientBrush.GradientStops> </LinearGradientBrush> </Button.Background>
注意<LinearGradientBrush.GradientStops>和<GradientStopCollection>元素是如何被省略的。這樣作是爲了簡潔和緊湊,而且能夠被智能化的分析器識別。首先GradientStops屬性是LinearGradientBrush的缺省屬性。其次GradientStops是GradientStopCollection類型並實現了IList<T>,此處T是GradientStop類型。有鑑於此,XAML分析器能夠推斷惟一能夠被嵌套在<LinearGradientBrush ... />中的是一個或多個GradientBrush的實例,每個被隱式地添加到GradientStopCollection中。
所以故事的寓意是XAML容許咱們以聲明方式建立類的實例,而且在設計用戶界面元素時能夠進行精細的控制。即使如此,XAML分析器是智能化的,只要有足夠的信息正確地建立對象圖(object graph)時,它就不須要咱們包含冗餘的代碼。
綜上所述,咱們已經學習了XAML的語法。大部分XAML很是簡單,但也有一些並不是顯而易見的內容:
接下來,讓咱們學習更多有關網格的佈局的內容,咱們還將在下一課學習XAML的附加屬性語法和如何鏈接事件。