【譯者注:這篇文章是翻譯自微軟官方的WP7 QuickStart的第二篇,講述WP下的XAML。部分內容加入了自己的理解和表達習慣。而翻譯此系列的主要目的一是為了練習英語,二是讓自己作為一個BI開發人員對WP7的開發有一個瞭解。部分翻譯不當的地方望各位高人指出批評指正】
原文地址:http://create.msdn.com/en-US/education/quickstarts/Creating_the_Windows_Phone_User_Interface_(XAML)
通常來說在Windows Phone下我們用Silverlight來建立應用程式,用XNA來建立遊戲。XAML就是在Silverlight下建立UI元素的一種聲明式語言,因此很多在螢幕上顯示的像控制項,圖形,文本等都可以通過它來建立。如果你熟悉網頁編程,你可以認為XAML和HTML是比較相似的,但相比HTML,XAML更強大。像HTML一樣,XAML也是有元素和屬性群組成的。然而,XAML是基於XML的,因此需要遵循XML的一些規則,包括格式化的要求等。你也許會問,“既然我有了Visual Studio或者Blend這樣的建立UI工具,那為什麼還要去關心XAML呢?”。即使有工具來產生這些標記,探尋和理解底層的東西也是經常需要的。另外,有時候通過代碼來手動建立UI反而會更容易一些。
此部分包含如下內容::
XAML樣本
XAML僅是過程代碼
屬性
XAML和視覺樹
不只是靜態UI
XAML樣本
下面的代碼執行個體用來建立一個按鈕。
XAML
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Height="72" Width="160" Content="Click Me" />
</Grid>
代碼運行效果大致如下:
Button控制項被指定為<Button>元素。Width和Height屬性用來指定按鈕的大小。<Grid>在你在Visual Studio中建立Windows Phone應用程式的時候就已經存在了,它被用來定位對象。關於Silverlight布局的更多資訊可以參考這裡。
你可以使用Visual Studio來產生XAML。比如,你可以在工具列裡拖拽一個按鈕來設計介面。
如下就是Visual Studio產生的程式碼。(你的也許看上去會略與不同)
XAML
<Grid x:Name="ContentGrid" Grid.Row="1">
<Button Content="Button" Height="72" HorizontalAlignment="Left"
Margin="152,273,0,0" Name="button1" VerticalAlignment="Top" Width="160" />
</Grid>
需要注意的是Visual Studio會填加一些額外的屬性,比如HorzontalAligment和Margin,他們用來定位按鈕的位置。這些額外的屬性也許有時候你是用不到的。當然在Visual Studio中也可以可視化地修改它們,但更多的時候,你可能都是在XAML裡直接修改他們。
使用像XAML這樣的聲明式語言的最大的好處就是,可以實現UI和代碼的分離。比如,在你的團隊中設計師設計UI然後將XAML提交給開發人員填加邏輯代碼。即使設計人員和開發人員是同一個人(通常都是),你也可以讓你的UI和代碼分離開。
XAML也是過程化代碼
【譯者註:過程化代碼?原文是Procedural Code,求更準確的理解】
XAML元素,比如<Button/>,跟在代碼裡執行個體化一個對象一樣。比如,下面的XAML代碼:
XAML
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Button Height="72" Width="160" Content="Click Me" />
</Grid>
下面的代碼是在c#裡建立的方式。
// Initialize the button
Button myButton = new Button();
// Set its properties
myButton.Width = 160;
myButton.Height = 72;
myButton.Content = "Click Me";
// Attach it to the visual tree, specifically as a child of
// the Grid object (named 'ContentPanel'). In other words, position
// the button in the UI.
ContentPanel.Children.Add(myButton);
對於UI來說,XAML相比用代碼去寫要更容易閱讀。然而,有時候通過代碼去動態建立UI也是很有必要的。
屬性
有兩種方式指定XAML的屬性值。
Attribute文法元素
Property文法元素
【譯者註:此部分求更準確的中文表達】
Attribute文法元素是上面提到過的類似HTML的形式,attribute=”值”。下面的樣本會建立一個紅色的Rectangle。Fill是以attribute的方式定義顏色的名稱的。
XAML
<Rectangle Fill="Red" />
或者,也可以通過Property的方式來指定。
XAML
<Rectangle>
<Rectangle.Fill>
<SolidColorBrush Color="Red" />
</Rectangle.Fill>
</Rectangle>
在這個樣本中,用的是SolidColorBrush對象賦給Fill屬性,而不是用字元Red。從這個樣本你也許會看出,Property的方式是以更囉嗦的方式做同樣的事。然而,並不是所有的值都支援attribute字串的。比如,你想指定一個對象裡的多個property,那麼就必須用property的方式。下面的樣本建立一個Rectangle,並且用漸進色。
XAML
<!-- This rectangle is painted with a diagonal linear gradient. -->
<Rectangle Width="200" Height="200">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
程式運行後如:
如你所見,Fill屬性用到了更複雜的LinearGradientBrush對象來建立漸進色。
XAML和視覺樹
在XAML中,某些元素可以包含其它的元素。這個父子關係指定類似對象的定位並且如何響應事件。考慮下面的樣本。
XAML
<Grid x:Name="ContentPanel" Background="Red" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Margin="20" Background="Blue" >
<TextBlock Name="firstTextBlock" FontSize="30">First TextBlock</TextBlock>
<TextBlock Name="secondTextBlock" FontSize="30">Second TextBlock</TextBlock>
<TextBlock Name="thirdTextBlock" FontSize="30">Third TextBlock</TextBlock>
</StackPanel>
</Grid>
紅色的Grid包含藍色的StackPanel。TextBlock包含在StackPanel中。此外,TextBlock在StackPanel中是按照縱向依次排開的。
下面的樹形結構表名了他們之間的關係.
除了考慮到內容是如何呈現的,視覺樹也會處理事件是如何被處理的。通常常見的事件都被冒泡到樹的頂端。比如,可以給StackPanel定義一個滑鼠左鍵處理代碼,MouseLeftButtonDown:
XAML
<Grid Background="Red" x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel Margin="20" Background="Blue" MouseLeftButtonDown="commonMouseHandler">
<TextBlock Name="firstTextBlock" FontSize="30" >First TextBlock</TextBlock>
<TextBlock Name="secondTextBlock" FontSize="30" >Second TextBlock</TextBlock>
<TextBlock Name="thirdTextBlock" FontSize="30" >Third TextBlock</TextBlock>
</StackPanel>
</Grid>
下面的代碼用來處理事件。
C#
private void commonMouseHandler(object sender, RoutedEventArgs e)
{
FrameworkElement feSource = e.OriginalSource as FrameworkElement;
switch (feSource.Name)
{
case "firstTextBlock":
firstTextBlock.Text = firstTextBlock.Text + " Click!";
break;
case "secondTextBlock":
secondTextBlock.Text = secondTextBlock.Text + " Click!";
break;
case "thirdTextBlock":
thirdTextBlock.Text = thirdTextBlock.Text + " Click!";
break;
}
}
運行代碼,點擊任何一個TextBlock,它上面顯示的資訊就會變化。這裡事件被冒泡到其父級元素處理。
下面示範了在樹中的事件冒泡。
1. 使用者單擊TextBlock
2. 事件冒泡到父級元素
3. 持續冒泡到樹根節點
因為事件是持續冒泡到樹根節點的,所以在Grid上來監聽MouseLeftButtonDown事件是一樣的。
不僅是靜態UI
在XAML中你可以做不僅是靜態UI可以做的事。你可以建立動畫,整合視頻,或者用標記語言來綁定資料。這些在接下來的內容將有講述。這裡展示一個簡單的動畫例子。點擊下面的Rectangle來看看效果。
XAML
<StackPanel Background="#FDF5E6">
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="myRectangle"
Storyboard.TargetProperty="Height">
<!-- This key frame resets the animation to its starting
value (30) at the beginning of the animation. -->
<LinearDoubleKeyFrame Value="30" KeyTime="0:0:0" />
<!-- Spline animations are used to create acceleration. This
SplineDoubleKeyFrame creates an animation that starts out slow
and then speeds up. The rectangle "falls". -->
<SplineDoubleKeyFrame KeySpline="0,0 1,0" Value="300"
KeyTime="0:0:0.8" />
<!-- This spline animation creates the "bounce" at the end where
the rectangle shortens its length quickly at first and then
slows down and stops. -->
<SplineDoubleKeyFrame KeySpline="0.10, 0.21 0.00, 1.0" Value="250"
KeyTime="0:0:1.5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</StackPanel.Resources>
<Rectangle x:Name="myRectangle" MouseLeftButtonDown="Mouse_Clicked" Fill="Blue"
Width="200" Height="30" />
</StackPanel>
C#
// When the user clicks the rectangle, the animation begins.
private void Mouse_Clicked(object sender, MouseEventArgs e)
{
myStoryboard.Begin();
}
這裡展示了使用XAML定義動態效果。StoryBoard中定義動畫的屬性,比如給哪個元素來定義動畫。其中的子項目定義LinearDoubleKeyFrame,執行動畫如何執行【譯者註:就是動畫的小姑】。關於動畫可以參考這裡。