摘要:Silverlight 課程第二部分:使用佈局管理 (木野狐譯)
【原文位址】Silverlight Tutorial Part 2: Using Layout Management
【原文發表日期】 Friday, February 22, 2008 5:55 AM
這是8個系列課程的第2部分,這個系列示範如何使用 Silverlight 2 的 Beta1 版本來建立一個簡單的 Digg 客戶端應用。這些課程請依次閱讀,將有助於您理解 Silverlight 的一些核心程式設計概念。
理解佈局管理
Silverlight 和 WPF 都支持一種靈活的佈局管理系統,能讓開發者和設計師輕鬆的定位 UI 上的控制項。該佈局系統對顯式指定坐標的控制項支持固定的定位模型;除此之外,還支持一種更為動態的定位模型,控制項和佈局能隨著瀏覽器的大小改變而自動改變其大小和方位。
在 Silverlight 和 WPF 中,開發者可以用佈局面板來協調包含在其中的控制項的位置和大小。Silverlight Beta1 中內建的佈局面板包括在 WPF 中最常用的3種:
- Canvas
- StackPanel
- Grid
Canvas面板
Canvas 面板是一種很基礎的佈局面板,它支持對其中的控制項採用絕對坐標定位。
你可以通過一種 XAML 特性— 「附加屬性」 對 Canvas 中的元素進行定位。用附加屬性,你可以指定控制項相對於其直接父 Canvas 控制項的上、下、左、右坐標的位置。附加屬性很有用,因為它讓父面板可以擴充其中包含的控制項的屬性集。Canvas 通過定義擴充屬性 Top 和 Left, 就能定義其中 Button (或其他任何 UI 元素)的 Left, Top,而不需要真正向 Button 類中添加這個屬性,或 修改 Button 類別。
我們可以向 Canvas 容器中添加兩個按鈕,指定其距離 Canvas 左側的距離為 50 像素,離上邊的距離則分別為 50 像素和 150 像素。使用如下 XAML 語法即可完成(其中 Canvas.Top 和 Canvas.Left 都是附加屬性的例子):
這些程式碼繪製的介面效果如下:
Canvas 適用於其中包含的 UI 元素比較固定的情形,但是如果你想向其中添加更多的控制項,或者 UI 需要改變大小或能夠移動,Canvas 顯得不太靈活。這時,你不得不忙於手寫程式碼來移動 Canvas 中的東西(這很痛苦)。應付這種動態的場景,更好的辦法通常是使用其它帶有相關功能的內建語意的佈局面板,如 StackPanel 和 Grid。
StackPanel
StackPanel 是一種簡單的佈局面板,它支持用行或列的方式來定位其中包含的控制項。StackPanel 常用於安排頁面上的一個很小的 UI 部分。
例如,我們可以用下面的 XAML 標籤在頁面上垂直的排布3個按鈕:
在運行時刻,StackPanel 會自動在一個垂直地堆疊(stack)中排列我們的按鈕(【譯註:這也是為什麼叫 StackPanel 的原因】),如下所示:
同樣,我們還可以把 Orientation 屬性設置為 Horizontal 而不是 Vertical (預設值):
這會讓 StackPanel 水平地排布3個按鈕,如下圖所示:
Grid面板
Grid 控制項是最靈活的佈局面板,它支持用多行和多列的方式排布控制項。在概念上,它和 HTML 裡的 Table (表格)類似。
不同於 Table 的是,你不需要將控制項內嵌到行/列元素中,而是通過定義 <Grid.RowDefinitions> 和 <Grid.ColumnDefinitions> 屬性來定義 Grid 的行和列。這兩個屬性需要定義在 <Grid> 標籤內。這樣之後,你就可以在其中的控制項上,用 XAML 的「附加屬性」語法指定它屬於哪一行、哪一列。
比如,我們可以用如下語法定義3行3列的 Grid 佈局,然後在其中放置4個按鈕:
以上程式碼會按下圖方式排列按鈕:
除了支持絕對尺寸定義(如:Height=」60〞),Grid 的 RowDefinition 和 ColumnDefinition 控制項還支持自動改變大小的模式(Height="Auto"),這樣會根據其中內容的尺寸自動改變 Grid 或 Row 的尺寸(你也可以指定最大或最小尺寸限制)。
Grid 的 Row 和 ColumnDefinitions 還支持叫做 「Proportional Sizing」 (按比例縮放)的特性。用這個特性,可以讓 Grid 的行列按相對比例的方式排放(如:你可以指定第二行的尺寸為第一行的2倍)。
你會發現 Grid 提供了非常多的功能和彈性 – 而它也許會成為你最終最常用的佈局面板控制項。
用佈局面板排布我們的 Digg 頁面
我們建立 Digg 例子的目標,是得到最終看起來像下圖的頁面:
要建立這種佈局,我們首先添加一個其中包含兩個 RowDefinition 的根級 Grid 面板。第一行的高度是 40 像素,而第二行則佔據所有剩下的空間(Height="*"):
小技巧:注意上面我將 Grid 的 ShowGridLines 屬性設置為 True. 這樣我們在運行時就能輕易的看到其行列的分界線:
接下來,我們在剛才的根級 Grid 面板裡,添加第二個 Grid 面板到第一行的位置,用它來排布頁面頂部的行(頁面頭部)。我們在其中建立3列:分別容納標題,搜尋文字框,和搜尋按鈕:
完成了這些後,我們就得到了 Digg 搜尋頁面的基本佈局,如下所示:
註:如果不用嵌套的 Grid,我們還可以用一個 2行3列的 Grid 來完成這個佈局,配合使用 Grid 的 ColSpan/RowSpan 特性來合併多個列中的內容(和你在 HTML table 中的做法類似)。我不這麼做,而是選擇使用嵌套 Grid 的原因,是因為這樣更便於學習和理解。
現在我們已經完成了佈局,接下來要做的是向其中添加控制項。
對頭部的行,我們用內建的 <Border> 控制項(設置其 CornerRadius 為 10,以得到圓角效果)並在其中添加一些文字來建立標題。我們用內建的 <WatermarkedTextBox> 控制項來建立第二列的搜尋文字框。並在第3列放置一個搜尋 <Button>. 然後我們在第二行放一些佔位文字,稍後我們會在這裡顯示搜尋結果。
註:下面我會直接在控制項中內嵌樣式信息(FontSize, Colors, Margins 等)。在這個系列課程中,晚一點我會Demo如何用 Styles 來提取、封裝這些設定到一個獨立的文件中(類似 CSS),以便於在整個應用程式中重用。
□
現在,讓我們運行一下應用程式,就會顯示出如下的介面:
動態改變應用程式的尺寸
你也許注意到了,在上面的 XAML 中我們的頂層控制項設置成了固定的高度和寬度:
這樣設置,我們的 Silverlight 應用程式會一直保持這個固定的尺寸。放大瀏覽器的尺寸會更明顯:
雖然在某些場合下,將內嵌的應用程式固定在 HTML 頁面的一個固定尺寸的區域內會很有用,但我們的 Digg 搜尋程式不一樣,我們寧願它能自動隨著瀏覽器而縮放,就像一個普通的 HTML 頁面那樣。
好消息是,這很容易實現。只要去除根控制項上的 Width 和 Height 屬性就行了:
這樣,我們的 Silverlight 應用程式就會自動擴充(或收縮),以填滿其嵌入的 HTML 容器。因為我們用來測試的 SilverlightTestPage.html 文件將 Silverlight 控制項放置在一個 HTML <div>元素中,並且其 CSS 設置中寬高均為 100%, 所以 Digg 應用程式最終會填滿整個瀏覽器:
注意頁面頭部中的文字內容的尺寸是如何隨著瀏覽器寬度而自動改變的:
當我們縮小瀏覽器尺寸時,帶水印的文字框和搜尋按鈕會保持同樣的尺寸,因為其 Grid 容器列的寬度是固定的。包含 「Digg Search」 標題的 <Border> 控制項卻會自動調整尺寸,因為其 Grid 列的寬度設置成了 Width=」*」.
我們不需要編寫一行程式碼就可以啟用這個佈局行為,Grid容器和佈局系統會為我們自動調整大小或流動其中的任何東西。
下一步
現在我們已經建立好了 Digg 程式的佈局結構,並且定義好了頁面頭部的行。
下一步,我們會實現該程式的搜尋行為 – 讓它在程式的終端用戶搜尋某個標題時,能夠真正的從 Digg.com 去獲取故事內容。
如果你想知道怎麼實現,請繼續閱讀下一篇: 使用 Networking 獲取資料並填充 DataGrid。
(翻譯:木野狐)