天天看點

Windows Phone 7 入門-XAML文法介紹

<b>什麼是</b><b> XAML</b><b>?</b>

XAML 是一種聲明性标記語言。如同應用于 .NET Framework 程式設計模型一樣,XAML 簡化了為 .NET Framework 應用程式建立 UI 的過程。您可以在聲明性 XAML 标記中建立可見的 UI 元素,然後使用代碼隐藏檔案(通過分部類定義與标記相連接配接)将 UI 定義與運作時邏輯相分離。XAML 直接以程式集中定義的一組特定後備類型表示對象的執行個體化。

下面的示例示範如何建立作為 UI 一部分的按鈕。此示例的目的僅在于供您初步了解 XAML 是如何表示常用 UI 程式設計形式的(它不是一個完整的示例)。

&lt;StackPanel&gt;

&lt;Button Content="Click Me"/&gt;

&lt;/StackPanel&gt;

<b>XAML </b><b>語</b><b>法概述</b>

<b>XAML </b><b>對</b><b>象元素</b>

此示例指定了兩個對象元素:&lt;StackPanel&gt;(含有内容,後面有一個結束标記)和 &lt;Button .../&gt;(自結束形式,包含幾個特性)。對象元素 StackPanel 和 Button 各映射到一個類名,這些類由 WPF 定義并且是 WPF 程式集的一部分。指定對象元素标記時會建立一條 XAML 處理指令來建立一個新執行個體。每個執行個體都是在分析和加載 XAML 時通過調用基礎類型的預設構造函數來建立的。

<b>特性</b><b>語</b><b>法(屬性)</b>

對象的屬性通常可表示為對象元素的特性。特性文法命名在特性文法中設定的屬性,後跟指派運算符 (=)。特性的值始終以包含在引号中的字元串的形式進行指定。

特性文法是最簡單有效的屬性設定文法,并且對于曾使用過标記語言的開發人員而言在使用中是最直覺的文法。例如,以下标記将建立一個具有紅色文本和藍色背景的按鈕,還将建立指定為 Content 的顯示文本。

&lt;Button Background="Blue" Foreground="Red" Content="This is a button"/&gt;

<b>屬性元素</b><b>語</b><b>法</b>

對于對象元素的某些屬性,特性文法是不可能實作的,因為無法在特性文法的引号和字元串限制内充分地表達提供屬性值所必需的對象或資訊。對于這些情況,可以使用另一個文法,即屬性元素文法。

屬性元素開始标記的文法為 &lt;類型名稱.屬性名稱&gt;。通常,該标記的内容是類型的一個對象元素,屬性會将該元素作為其值。指定内容之後,必須用一個結束标記結束屬性元素。結束标記的文法為 &lt;/類型名稱.屬性名稱&gt;。

如果可以使用特性文法,那麼使用特性文法通常更為友善,且能夠實作更為精簡的标記,但這通常隻是一個風格的問題,而不屬于技術限制。下面的示例示範了在前面的特性文法示例中設定的相同屬性,但這次對 Button 的所有屬性使用了屬性元素文法。

&lt;Button&gt;

&lt;Button.Background&gt;

&lt;SolidColorBrush Color="Blue"/&gt;

&lt;/Button.Background&gt;

&lt;Button.Foreground&gt;

&lt;SolidColorBrush Color="Red"/&gt;

&lt;/Button.Foreground&gt;

&lt;Button.Content&gt;

This is a button

&lt;/Button.Content&gt;

&lt;/Button&gt;

<b>集合</b><b>語</b><b>法</b>

XAML 語言包含一些優化,可以生成可讀性更好的标記。其中的一項優化是:如果某個特定屬性采用集合類型,則您在标記中聲明為該屬性的值内的子元素的項将成為集合的一部分。在這種情況下,子對象元素的集合是設定為集合屬性的值。

&lt;LinearGradientBrush&gt;

&lt;LinearGradientBrush.GradientStops&gt;

&lt;!-- no explicit new GradientStopCollection, parser knows how to find or create --&gt;

&lt;GradientStop Offset="0.0" Color="Red" /&gt;

&lt;GradientStop Offset="1.0" Color="Blue" /&gt;

&lt;/LinearGradientBrush.GradientStops&gt;

&lt;/LinearGradientBrush&gt;

<b>XAML </b><b>内容屬性</b>

XAML 指定了一個語言功能,通過該功能,一個類可以指定它的一個且僅一個屬性為 XAML 内容屬性。該對象元素的子元素用于設定該内容屬性的值。換言之,僅對内容屬性而言,您可以在 XAML 标記中設定該屬性時省略屬性元素,并在标記中生成更直覺的父級/子級形式。

&lt;Border&gt;

&lt;TextBox Width="300"/&gt;

&lt;/Border&gt;

&lt;!--explicit equivalent--&gt;

&lt;Border.Child&gt;

&lt;/Border.Child&gt;

作為 XAML 語言的規則,XAML 内容屬性的值必須完全在該對象元素的其他任何屬性元素之前或之後指定。例如,下面的标記無法進行編譯:

<a>複制</a>

&lt;Button&gt;I am a

&lt;Button.Background&gt;Blue&lt;/Button.Background&gt;

blue button&lt;/Button&gt;

<b>文本内容</b>

有少量 XAML 元素可直接将文本作為其内容來處理。若要實作此功能,必須滿足以下條件之一:

類型必須聲明一個類型轉換器,該類型轉換器将文本内容用作其初始化文本。例如,&lt;Brush&gt;Blue&lt;/Brush&gt;。這種情況實際上并不常見。

類型必須為已知的 XAML 語言基元。

<b>内容屬性和集合</b><b>語</b><b>法</b><b>組</b><b>合</b>

請看以下示例:

&lt;Button&gt;First Button&lt;/Button&gt;

&lt;Button&gt;Second Button&lt;/Button&gt;

&lt;StackPanel.Children&gt;

&lt;!--&lt;UIElementCollection&gt;--&gt;

&lt;!--&lt;/UIElementCollection&gt;--&gt;

&lt;/StackPanel.Children&gt;

<b>特性</b><b>語</b><b>法(事件)</b>

&lt;Page

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

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

x:Class="ExampleNamespace.ExamplePage"&gt;

&lt;Button Click="Button_Click" &gt;Click Me!&lt;/Button&gt;

&lt;/Page&gt;

<b>XAML </b><b>中的大小寫和空白</b>

WPF XAML 處理器和序列化程式将忽略或删除所有無意義的空白,并規範化任何有意義的空白。這與 XAML 規範的預設空白行為建議一緻。通常,隻有當您在 XAML 内容屬性中指定字元串時,此行為的重要性才會展現出來。簡言之,XAML 将空格、換行符和制表符轉化為空格,如果它們出現在一個連續字元串的任一端,則保留一個空格。有關 XAML 空白處理的完整說明不屬于本主題的讨論範圍。

<b>标記擴</b><b>展</b>

标記擴充是一個 XAML 語言概念。當用于提供特性文法的值時,大括号({ 和 })表示标記擴充用法。此用法訓示 XAML 處理系統不要像通常那樣将特性值視為一個文本字元串或者可轉換為字元串的值。

&lt;Page.Resources&gt;

&lt;SolidColorBrush x:Key="MyBrush" Color="Gold"/&gt;

&lt;Style TargetType="Border" x:Key="PageBackground"&gt;

&lt;Setter Property="Background" Value="Blue"/&gt;

&lt;/Style&gt;

...

&lt;/Page.Resources&gt;

&lt;Border Style="{StaticResource PageBackground}"&gt;

<b>類</b><b>型</b><b>轉換</b><b>器</b>

&lt;Button Margin="10,20,10,30" Content="Click me"/&gt;

&lt;Button Content="Click me"&gt;

&lt;Button.Margin&gt;

&lt;Thickness Left="10" Top="20" Right="10" Bottom="30"/&gt;

&lt;/Button.Margin&gt;

<b>說</b><b>明</b>

<b>XAML </b><b>根元素和</b><b> XAML </b><b>命名空</b><b>間</b>

根元素還包含特性 xmlns 和 xmlns:x。這些特性向 XAML 處理器指明哪些 XAML 命名空間包含标記将要作為元素引用的後備類型的類型定義。xmlns 特性明确訓示預設的 XAML 命名空間。在預設的 XAML 命名空間中,可以不使用字首指定标記中的對象元素。對于大多數 WPF 應用程式方案以及 SDK 的 WPF 部分中給出的幾乎所有示例,預設的 XAML 命名空間均映射到為 WPF 命名空間 http://schemas.microsoft.com/winfx/2006/xaml/presentation。xmlns:x 特性訓示另外一個 XAML 命名空間,該命名空間映射 XAML 語言命名空間 http://schemas.microsoft.com/winfx/2006/xaml。

使用 xmlns 定義用法範圍和名稱範圍映射的做法符合 XML 1.0 規範。XAML 名稱範圍與 XML 名稱範圍的不同僅在于:XAML 名稱範圍還包含有關進行類型解析和分析 XAML 時名稱範圍的元素如何受類型支援的資訊。

請注���,隻有在每個 XAML 檔案的根元素上,xmlns 特性才是絕對必需的。xmlns 定義将适用于根元素的所有子代元素(此行為也符合 xmlns 的 XML 1.0 規範。)同時允許根以下的其他元素上具有 xmlns 特性,這些特性将适用于定義元素的任何子代元素。但是,頻繁定義或重新定義 XAML 命名空間可能會導緻 XAML 标記樣式難以閱讀。

其 XAML 處理器的 WPF 實作包括可識别 WPF 核心程式集的基礎結構。已知 WPF 核心程式集包含支援 WPF 到預設 XAML 命名空間的映射的類型。這是通過屬于項目生成檔案以及 WPF 生成和項目系統一部分的配置來實作的。是以,為了引用來自 WPF 程式集的 XAML 元素,隻需将預設 XAML 命名空間聲明為預設 xmlns。

<b>x: </b><b>前</b><b>綴</b>

在上面的根元素示例中,字首 x: 用于映射 XAML 命名空間 http://schemas.microsoft.com/winfx/2006/xaml,該命名空間是支援 XAML 語言構造的專用 XAML 命名空間。在這整個 SDK 的項目模闆、示例以及文檔中,此 x: 字首用于映射該 XAML 命名空間。XAML 語言的 XAML 命名空間包含多個将在 XAML 中頻繁用到的程式設計構造。下面列出了将用到的最常見的 x: 字首程式設計構造:

<b>XAML </b><b>中的自定</b><b>義</b><b>前</b><b>綴</b><b>和自定</b><b>義類</b><b>型</b>

對于您自己的自定義程式集或 PresentationCore、PresentationFramework 和 WindowsBase 的 WPF 核心以外的程式集,可以将該程式集指定為自定義 xmlns 映射的一部分。隻要該類型能夠正确地實作以支援您所嘗試的 XAML 用法,就可以在 XAML 中引用該程式集中的類型。

下面是一個說明自定義字首如何在 XAML 标記中工作的基本示例。字首 custom 在根元素标記中定義,并映射為随應用程式一同打包并可用于該應用程式的一個特定程式集。此程式集包含 NumericUpDown 類型,實作該類型的目的是在支援正常 XAML 用法之外,還可以使用允許在 WPF XAML 内容模型的此特定點執行插入的類繼承。通過使用該字首,此 NumericUpDown 控件的一個執行個體聲明為對象元素,以便 XAML 分析器可找到包含該類型的 XAML 命名空間,進而找到包含該類型定義的後備程式集的位置。

xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"

&gt;

&lt;StackPanel Name="LayoutRoot"&gt;

&lt;custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/&gt;

...&lt;/StackPanel&gt;

<b>事件和</b><b> XAML </b><b>代</b><b>碼隐</b><b>藏</b>

大多數 WPF 應用程式既包括 XAML 标記,也包括代碼隐藏。在一個項目中,XAML 編寫為 .xaml 檔案,而 CLR 語言(如 Microsoft Visual Basic .NET 或 C#)用于編寫代碼隐藏檔案。在 WPF 程式設計和應用程式模型中對 XAML 檔案進行标記編譯時,XAML 檔案的 XAML 代碼隐藏檔案的位置是通過如下方式來辨別的:以 XAML 的根元素的 x:Class 特性形式指定一個命名空間和類。

在目前已介紹的示例中,您已看到幾個按鈕,但還沒有一個按鈕具有任何關聯的邏輯行為。為對象元素添加行為的主要應用程式級機制是使用元素類的現有事件,并為在運作時引發該事件時調用的該事件編寫特定的處理程式。事件名稱以及要使用的處理程式的名稱在标記中指定,而實作處理程式的代碼在代碼隐藏中定義。

Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

Dim b As Button = e.Source

b.Foreground = Brushes.Red

End Sub

請注意,代碼隐藏檔案使用 CLR 命名空間 ExampleNamespace 并将 ExamplePage 聲明為該命名空間内的一個分部類。這相當于在标記根中提供的 ExampleNamespace.ExamplePage 的 x:Class 特性值。WPF 标記編譯器将通過從根元素類型派生一個類,為編譯的任何 XAML 檔案建立一個分部類。當您提供也會定義同一分部類的代碼隐藏時,将在與編譯的應用程式相同的命名空間和類中組合生成的代碼。

<b>路由事件</b>

<b>XAML </b><b>命名元素</b>

&lt;StackPanel Name="buttonContainer"&gt;

&lt;Button Click="RemoveThis"&gt;Click to remove this button&lt;/Button&gt;

Private Sub RemoveThis(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)

Dim fe As FrameworkElement = e.Source

If (buttonContainer.Children.Contains(fe)) Then

buttonContainer.Children.Remove(fe)

End If

<b>附加屬性和附加事件</b>

XAML 指定了一個語言功能,該功能允許對任何元素指定某些屬性或事件,而不管要設定屬性或事件的元素的類型定義中是否存在該屬性或事件。該功能的屬性版本稱為附加屬性,事件版本稱為附加事件。從概念上講,可以将附加屬性和附加事件視為可以在任何 XAML 元素/對象執行個體上設定的全局成員。但是,元素/類或更大的基礎結構必須支援附加值的後備屬性存儲。

通常通過特性文法來使用 XAML 中的附加屬性。在特性文法中,您可以采用“所有者類型.屬性名”的形式指定附加屬性。

表面上,這與屬性元素用法類似,但在這種情況下,您指定的“所有者類型”始終是一種與從中要設定附加屬性的對象元素不同的類型。“所有者類型”這種類型提供 XAML 處理器為擷取或設定附加屬性值所需要的通路器方法。

使用附加屬性的最常見方案是使子元素能夠向其父元素報告屬性值。

&lt;DockPanel&gt;

&lt;Button DockPanel.Dock="Left" Width="100" Height="20"&gt;I am on the left&lt;/Button&gt;

&lt;Button DockPanel.Dock="Right" Width="100" Height="20"&gt;I am on the right&lt;/Button&gt;

&lt;/DockPanel&gt;

本文轉自linzheng 51CTO部落格,原文連結:http://blog.51cto.com/linzheng/1079236