Bài 7: Layout control trong Windows Phone


Trước khi tiến hành thiết kế giao diện trong Windows Phone thì bạn cần hiểu cách sử Layout Control.

Layout control nó giống như bản vẽ kỹ thuật giúp ta dễ dàng tổ chức sắp xếp các control khác theo ý đồ thiết kế.

Windows phone hỗ trợ một số các Layout control phổ biến như sau:

  1. Grid Layout –Sắp xếp các đối tượng  theo dòng và cột
  2. Canvas Layout- Sắp xếp các đối tượng theo tọa độ
  3. Stackpanel Layout– Sắp xếp các đối tượng theo cơ chế stack theo hướng từ trên dưới hoặc từ trái qua (tùy theo orientation)
  4. WrapPanel Layout– Sắp xếp các đối tượng theo dòng, khi nào hết chỗ chứa thì xuống dòng.
  5. Border Layout– Tạo đường viên bao bọc cho các đối tượng.
  6. ScrollView control– tạo Scrollview khi nội dung vượt quá khung chứa.

Mỗi một layout, control có những đặc tính và chức năng khác nhau. Tui sẽ lần lượt trình bày từng loại Layout, control:

1) Grid Layout

  • Grid sắp xếp các thành phần con theo dòng và cột.
  • Dễ dàng mở rộng nếu cần.
  • Phải định nghĩa các dòng và cột trước khi dùng.

Bạn có thể tưởng tượng mỗi dòng của Grid layout giống như thẻ <tr> và mỗi cell của nó là thẻ <td> trong HTML.

Ví dụ ta muốn khai báo một Grid có 3 dòng 3 cột với thông số sau:


<Grid x:Name="LayoutRoot" >

<Grid.ColumnDefinitions>

<ColumnDefinition Width="150"/>

<ColumnDefinition Width="170"/>

<ColumnDefinition Width="160"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="150"/>

<RowDefinition Height="100"/>

<RowDefinition Height="200"/>

</Grid.RowDefinitions>

</Grid>

– Dòng 1 có độ cao là 150, dòng 2 có độ cao là 100, dòng 3 có độ cao là 200

– Cột 1 có độ rộng là 150, cột 2 có độ rộng là 170 và cột 3 có độ rộng là 160

Ta xem kết quả:

wp7_1Để đưa các control vào theo đúng dòng và cột ta làm như sau:


<Grid x:Name="LayoutRoot" >

<Grid.ColumnDefinitions>

<ColumnDefinition Width="150"/>

<ColumnDefinition Width="170"/>

<ColumnDefinition Width="160"/>

</Grid.ColumnDefinitions>

<Grid.RowDefinitions>

<RowDefinition Height="150"/>

<RowDefinition Height="100"/>

<RowDefinition Height="200"/>

</Grid.RowDefinitions>

<Button Content="0,0" Grid.Row="0" Grid.Column="0"/>

<Button Content="0,1" Grid.Row="0" Grid.Column="1"/>

<Button Content="0,2" Grid.Row="0" Grid.Column="2"/>

<Button Content="1,0" Grid.Row="1" Grid.Column="0"/>

<Button Content="1,1" Grid.Row="1" Grid.Column="1"/>

<Button Content="1,2" Grid.Row="1" Grid.Column="2"/>

<Button Content="2,0" Grid.Row="2" Grid.Column="0"/>

<Button Content="2,1" Grid.Row="2" Grid.Column="1"/>

<Button Content="2,2" Grid.Row="2" Grid.Column="2"/>

</Grid>

Ta thấy XAML ở trên sử dụng Attach Property Syntax để thiết lập giá trị thuộc tính cho các control.

Ví dụ:

<Button Content=”2,0″ Grid.Row=”2″ Grid.Column=”0″/>

Tức là đưa Button này vào dòng 2 (do Grid.Row=”2″) cột 0 (do Grid.Column=”0″).

Ta xem kết quả:

wp7_22) Canvas Layout

-Canvas sắp xếp vị trí các thành phần con dựa trên khoảng cách tuyệt đối từ thành phần đó đến lề trên (Canvas.Top) và trái (Canvas.Left) của canvas.

Chú ý:

– Top càng tăng thì đối tượng càng di chuyển xuống dưới, Top càng giảm thì đối tượng di chuyển lên trên.

– Left càng tăng thì đối tượng di chuyển qua phải, Left càng giảm thì đối tượng di chuyển qua trái.

ví dụ XAML:


<Canvas>

<Ellipse Name="myEllipse"

Canvas.Left="100"

Canvas.Top="70"

Width="100"

Height="100"

Fill="LawnGreen" />

</Canvas>

Kết quả:

wp7_3

– Các thành phần con có thể nằm đè lên nhau,  Khi đó, sử dụng thuộc tính ZIndex để đặt thứ tự xếp trên dưới cho các thành phần con:


<Canvas>

<Ellipse Canvas.Left="38"  Canvas.Top="81"  Canvas.ZIndex="2"

Width="100" Height="100" Fill="Green"/>

<Ellipse Canvas.Left="84" Canvas.Top="48"

Width="100" Height="100"  Canvas.ZIndex="1"  Fill="Yellow"/>

<Ellipse Canvas.Left="24" Canvas.Top="10"

Width="100" Height="100" Fill="Red" />

</Canvas>

Kết quả:

wp7_4Ta có thể di chuyển các đối tượng trên Canvas bằng coding behind như sau:

Tui đưa ra 1 ví dụ là cho phép 1 hình tròn di chuyển bất kỳ vị trí Top, Left trên màn hình.

bạn tạo 1 Project đặt tên MovingBall.

wp7_5Bạn tạo MainPage.xaml như sau:


<phone:PhoneApplicationPage
x:Class="MovingBall.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Canvas HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="480">
<Ellipse x:Name="myBall" Height="100" Canvas.Left="153" Stroke="Black" Canvas.Top="10" Width="100">
<Ellipse.Fill>
<RadialGradientBrush GradientOrigin="0.5,0.75">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Green" Offset="1"/>
</RadialGradientBrush>

</Ellipse.Fill>
</Ellipse>
<Button x:Name="btnMove" Content="Move Ball" Canvas.Left="135" Canvas.Top="280"/>
</Canvas>

</phone:PhoneApplicationPage>

Giao diện tạm thời nhưu sau:

wp7_6Yêu cầu:

– Bấm vào nút “Move Ball”: Nút này sẽ ẩn đi (tên là btnMove) và Ball (tên là myBall)sẽ di chuyển lung tung trên màn hình theo hướng từ trên xuống và xàng qua xàng lại từ trái qua phải,

– Khi nào Ball chạm đáy màn hình thì Button Move Ball hiển thị trở lại và Ball về vị trí cũ.

Ta tiến hành coding MainPage.xaml.cs như sau:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using MovingBall.Resources;
//thư viện để sử dụng DispatcherTimer
using System.Windows.Threading;

namespace MovingBall
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();

// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}
//khai báo đối tượng DispatcherTimer để kích hoạt hẹn giờ
DispatcherTimer timer = new DispatcherTimer();

private void btnMove_Click(object sender, RoutedEventArgs e)
{
//cứ 100 mili giây thì thực hiện 1 lần
timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
timer.Tick += timer_Tick;
timer.Start();
btnMove.Visibility = Visibility.Collapsed;
}
Random rd = new Random();
int top = 0, left = 0;
void timer_Tick(object sender, EventArgs e)
{

top+=rd.Next(0,20);
left = rd.Next(0, 400);
doMoveBall();
if(top>=600)
{
top = 0;
left = 0;
doMoveBall();
timer.Stop();
btnMove.Visibility = Visibility.Visible;
}
}
public void doMoveBall()
{
//Thiết lập qua trái -phải
Canvas.SetLeft(myBall, left);
//thiết lập từ trên xuống
Canvas.SetTop(myBall, top);
}

}
}

 3)Stackpanel Layout

Sắp xếp các đối tượng theo cơ chế stack theo hướng từ trên dưới hoặc từ trái qua (tùy theo orientation)


<StackPanel x:Name="LayoutRoot" >

<Ellipse Width="100" Height="100" Fill="Green"/>

<Ellipse Width="100" Height="100" Fill="Yellow"/>

<Ellipse Width="100" Height="100" Fill="Red" />

</StackPanel>

Ta xem kết quả:

wp7_7

Mặc định nó sẽ xếp theo chiều dọc từ trên xuống dưới, Ta dùng thuộc tính Orientation để sắp theo chiều ngang:


<StackPanel x:Name="LayoutRoot" Orientation="Horizontal">
<Ellipse Width="100" Height="100" Fill="Green"/>
<Ellipse Width="100" Height="100" Fill="Yellow"/>
<Ellipse Width="100" Height="100" Fill="Red"/>
</StackPanel>

Ta xem kết quả:

wp7_8Ta cũng có thể thay đổi vị trí thứ tự xuất của các control nằm bên trong Stackpanel bằng cách thay đổi FlowDirection=”RightToLeft” hoặc FlowDirection=”LeftToRight”.

Mặc định nó là FlowDirection=”LeftToRight”, nếu như ta đổi thành FlowDirection=”RightToLeft” thì hình trên thay đổi như sau:

wp7_9Ta xem xaml:


<StackPanel x:Name="LayoutRoot"
Orientation="Horizontal"
FlowDirection="RightToLeft">
<Ellipse Width="100" Height="100" Fill="Green"/>
<Ellipse Width="100" Height="100" Fill="Yellow"/>
<Ellipse Width="100" Height="100" Fill="Red"/>
</StackPanel>

4) WrapPanel Layout Sắp xếp các đối tượng theo dòng, khi nào hết chỗ chứa thì xuống dòng.

– Để sử dụng được WrapPanel ta cần tải thư viện Windows Phone Toolkit về sau đó cấu hình namespace để sử dụng (cách khai báo namespace đã hướng dẫn ở các bài trước.

– Ta làm theo các bước sau:

Bước 1:

Bấm chuột phải vào Reference/ chọn Manage NuGet Packages…:

wp7_10

Bước 2:

Màn hình Manage NuGet Packages hiển thị ra như bên dưới đây, bạn chọn từng bước theo số thứ tự mà Tui đánh dấu:

wp7_11số 1: Bạn click chọn Online trước

số 2: Bạn nhận từ khóa toolkit

Số 3: Bạn chọn gói Windows Phone Toolkit rồi bấm nút Install.

Sau khi bấn Install, hệ thống sẽ tiến hành tải và cài đặt… bạn cần chờ trong giây lát….:

wp7_12Sau khi cài hoàn tất thì Windows Phone Toolkit sẽ được đánh dấu Tick tức là bạn bắt đầu sử dụng được: wp7_13Tới bước trên là đã thành công, bạn bấm nút Close để trở về Project của mình, bạn thấy Project sẽ có một số thay đổi như sau:

wp7_14(Bạn chỉ cần tải 1 lần mà thôi, các Project khác nếu như có sử dụng thư viện này thì bạn chỉ cần tham chiếu tới dll của nó là ok – Tui sẽ nói cách tham chiếu ở các bài tiếp sau này nếu các bạn chưa biết).

Bước 3:– Khai báo Namespace để sử dụng Windows Phone Toolkit.

trong phone:PhoneApplicationPage bạn khai báo sử dụng namespace như sau:


xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

wp7_15Hình trên Tui chụp là cách sử dụng WrapPanel, bạn chỉ cần lấy prefix là toolkit (đặt tên gì là do bạn tuy nhiên cần mang tính gợi nhớ).

Để truy suất tới tất cả các thành phần thuộc Windows Phone Toolkit thì bạn chỉ cần viết

toolkit : [tên thành phần].

Windows phone toolkit cung cấp hàng loạt các control hữu ích sau (ta sẽ sử dụng rất nhiều trong các bài tập kế tiếp).

  • AutoCompleteBox
  • ContextMenu
  • CustomMessageBox
  • DateTimeConverters
  • DateTimePickers
  • Effects – SlideInEffect, TiltEffect and TurnstileFeatherEffect
  • ExpanderView
  • HubTile
  • ListPicker
  • LongListMultiSelector
  • Map extensions
  • PhoneTextBox
  • RatingControl
  • ToggleSwitch
  • TransferControl
  • Navigation transitions
  • WrapPanel

– Trước tiên ta sử dụng WrapPanel để layout các control:

Mặc định WrapPanel sắp xếp control theo hướng nằm ngang từ trái qua (Orientation=”Horizontal“) – tức là nếu như không thiết lập Orientation thì nó tự động là Horizontal, khi nào hết chỗ chứa thì nó tự động xuống dòng (ở đây tui thiết lập Orientation luôn):


<toolkit:WrapPanel Orientation="Horizontal">
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
<Ellipse Width="100" Height="100" Fill="Yellow"></Ellipse>
</toolkit:WrapPanel>

wp7_16

Nếu bạn thay bằng Orientation=”Vertical” thì các control sẽ được sắp từ trên xuống, khi nào hết cột thì chuyển qua cột mới:

<toolkit:WrapPanel Orientation=”Vertical”>

wp7_17Và bạn cũng có thể thiết lập:  FlowDirection=”RightToLeft” hay FlowDirection=”LeftToRight” để xem hướng xuất hiện, ví dụ bây giờ tui thiết lập FlowDirection=”RightToLeft”  cho Wrapanel thì kết quả như sau:

<toolkit:WrapPanel Orientation=”Vertical” FlowDirection=”RightToLeft”>

wp7_185) Border Layout Tạo đường viên bao bọc cho các đối tượng.

– Border không phải là một layout controls thật sự.

– Dùng để tạo khung cho các thành phần

– Thường được dùng làm khung cho GridStackPanel, WrapPanel, Canvas…. tùy…

Ví dụ ta xem hình Border layout dưới đây:

wp7_19Tui có đoạn mã khuyết XAML dưới đây, bạn thử sửa lại cho hoàn thiện rồi tiến hành chạy (sửa mấy chỗ Tui để dấu chấm hỏi ???):


<Border BorderThickness="8,4,2,1"  CornerRadius="50" >

<Border.BorderBrush>

<LinearGradientBrush EndPoint="0.5,1"

StartPoint="0.5,0">

<GradientStop Color="???" Offset="0"/>

<GradientStop Color="???" Offset="1"/>

</LinearGradientBrush>

</Border.BorderBrush>

<Grid x:Name="ContentPanel">
</Grid>

</Border>

Bạn cần biết một vài thông số thường dùng của Border:

BorderThickness=”8,4,2,1″ –> Độ dày của đường viền (left=8, top=4, right=2, bottom=1)

BorderBrush –> màu của đường viền

CornerRadius –> Bo góc đường viền.

6) ScrollView control tạo Scrollview khi nội dung vượt quá khung chứa.


<ScrollViewer Height="550">

<TextBlock>

[noi dung dai]

</TextBlock>

</ScrollViewer>

Nếu muốn Scroll theo coding thì:

Dùng 2 phương thức ScrollToVerticalOffset() và ScrollToHorizontalOffset() để scrollviewer có thể scroll từng đoạn:


private void btnScrollTop_Click(object sender, RoutedEventArgs e)

{

if (myscrollview.ScrollableHeight +     myscrollview.VerticalOffset < myscrollview.ExtentHeight)

myscrollview.ScrollToVerticalOffset      (5 + myscrollview.VerticalOffset);

}

private void btnScrollBottom_Click(object sender, RoutedEventArgs e)

{

if (myscrollview.VerticalOffset >=0)

myscrollview.ScrollToVerticalOffset  (myscrollview.VerticalOffset-5);

}

Với myscrollview là tên của ScrollViewwp7_20 Như vậy Tui đã trình bày sơ sơ qua về một số Layout control rất cần thiết cho quá trình thiết kế giao diện, các bạn cần nghiên cứu nó kỹ, bài tập sau Tui sẽ trình bày về các control cơ bản như: Textbox, Textbloc, Button ….

Chúc các bạn thành công.

2 responses

  1. Tại mục 4) WrapPanel Layout
    Bước 2: em đã cài đặt thành công toolkit rồi nhưng ở references nó không hiện ra như ở hình của thầy! giờ em phải làm sao đây thầy 😦

  2. thầy ơi, thay vì dùng scroll viewer để đọc truyện lượt xuống, em có cách nào vuốt ngang không thầy, dạ nghĩa là vuốt qua từng page thưa thầy

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: