Bài 49: Cách debug ứng dụng trên thiết bị Android bằng WIFI (không cần cắm USB Cable)


Hiện nay trên Store của Google cũng có rất nhiều App miễn phí cho phép lấy IP của thiết bị để có thể kết nối tới PC mà không cần dùng Cable. Nhưng cũng nhiều khi phải Rooted máy và cũng mất công phải cài phần mềm.

Trong bài này Tui sẽ hướng dẫn các bạn cách Debug ứng dụng Android trên thiết bị thật thông qua WIFI nội bộ giữa  Thiết bị và PC (chú ý là không cần kết nối internet) và cũng không cần cài đặt thêm bất cứ phần mềm nào. Đặc biệt khi cùng kết hợp với phần mềm “droidAtScreen-1.1.jar” thì các bạn có thể Demo ứng dụng một cách hoàn hoản, nhất là dành cho những bạn phải thuyết trình ứng dụng hay giảng dạy…

android_49_1Các bước cụ thể như sau:

Bước 1:

Bật chức năng WI-FI hotspot trên thiết bị di động sử dụng Android, Bước này Tui chụp bằng điện thoại thật của Tui, Model SamSung S2, GT-I9100 (các dòng khác chắc nó cũng lủi ở góc nào đó). Cái chức năng này chắc chắn đa phần mọi người đều biết, nhưng Tui sẽ hướng dẫn thật chi tiết vì còn nhiều Sinh Viên mới tiếp cận.

- Vào Setting như màn hình dưới đây:

android_49_2- Sau khi bấm Setting thì màn hình bến dưới xuất hiện, bạn tìm tới nhóm Wireless and networks:

android_49_3

- Nhấn chọn More Settings, màn hình xuất hiện như bên dưới :

android_49_4

- Ta nhấn chọn Tethering and portable hotspot…: Tại màn hình mới này ta kích hoạt nó lên như hình bên dưới, sau khi kích hoạt (thành màu xanh xanh đó bạn) thì nhấn vào Portable Wi-Fi h……

android_49_5

- Sau khi nhấn chọn Portable Wi-Fi h…… thì màn hình sau xuất hiện:

android_49_6

- Tại màn hình trên, để cấu hình sửa đổi tên Trạm Phát wifi và mật khẩu của trạm phát, bạn nhấn vào nút Configure mà tui khoanh màu vàng đó…. :

Để cho dễ dàng tìm kiếm tên Trạm phát WIFI bạn nên đặt tên cho nó, ví dụ Tui đặt trạm phát WIFI tại thiết bị của tui là drthanh

android_49_7

- Đồng thời cũng đặt mật khẩu cho trạm phát rồi nhấn nút Save.

 Bước 2:

Kết nối PC tới trạm phát sóng WIFI mà bạn vừa tạo ở bước 1.

android_49_8Bạn tìm tới trạm phát nào có tên drthanh được cấu hình, chọn nó và bấm Connect. Nhập mật khẩu để tiến hành kết nối.

Khi kết nối thành công thì Thiết bị của bạn sẽ thông báo là có Máy nào kết nối tới hay không, địa chỉ IP là gì, MAC là gì…

Chú ý phải đảm bảo bước 2 kết nối thành công.

Bước 3:

Tìm địa chỉ IP của trạm phát sóng WIFI (tức lại địa IP của thiết bị di động đó), các bước đơn giản làm như sau:

Nhấn tổ hợp phím Windows + R để mở của sổ Run

Tại cửa số này bạn gõ lệnh cmd như hình chụp để mở màn hình Command line:

android_49_9Nhấn OK:

android_49_14Tại dấu nhắc lệnh, bạn gõ lệnh ipconfig để hệ thống hiển thị địa chỉ IP của trạm phát.

Sau khi gõ lệnh và nhấn phím Enter, bạn có kết quả sau (tùy vào máy bạn nhé):

android_49_15Bạn nhìn vào dòng Default Gateway, thấy IP 192.168.43.1 , đây chính là địa chỉ IP của Trạm phát WIFI. Địa chỉ này có thể khác nhau tùy thuộc vào máy tính cũng như thiết bị của bạn.

Bước 4:

Tạo tập tin Bat để dễ dàng kết nối từ PC tới trạm phát WIFI (tức là từ PC tới thiết bị điện thoại của bạn).

Mục đích Tui hướng dẫn các bạn tạo file Bat để có thể chạy cùng nhiều lệnh 1 lúc, và bất cứ lúc nào muốn chạy chỉ cần Double click vào nó–> đỡ mất thời gian và lại vô cùng easy.

Trước tiên bạn cần vào đúng nơi lưu trữ tập tin adb.exe, nó nằm trong thư mục sdk/platform-tools (tùy vào bạn sao chép):

android_49_16Bạn nhìn vào hình trên là biết được cần phải tìm ở chỗ nào.

Bạn thấy Tui khoanh đỏ 2 file không? adb.exe là của Android. Còn runwifi.bat là do Tui tạo ra, cách thức tạo file bat này như sau:

- Bấm chuột phải ngay tại màn hình này/ chọn New/ Text Document như hình bên dưới:

android_49_17Kết quả cho ta mặc định như sau:

android_49_18Bạn thấy đó, mặc định tập tin “New Text Document.txt” được tạo ra, bây giờ bạn double click vào nó để mở lên , sau đó tiến hành gõ lệnh:

android_49_19Tui gõ 3 dòng lệnh:

Dòng 1:

adb tcpip 5555

Dòng 2:

adb connect 192.168.43.1

Dòng 3:

pause

Dòng 1 là tạo port, dòng 2 là kết nối tới trạm phát WIFI, đó chính là IP mà ta tìm được từ trạm phát ở bước 3, dòng 3 là lệnh pause mục đích để ngừng lại màn hình cho phép ta xem kết quả (nếu không có lệnh này thì chạy xong nó tắt luôn, ta không xem được).

Sau khi nhập lệnh xong, ta đóng tập tin này và đổi tên nó thành runwifi.bat (đặt tên nào là kệ bạn).

android_49_20Bước 5:

Thực thi lệnh runwifi.bat bằng cách double click vào nó:

android_49_21Ban quan sát màn hình trên, thấy đó….. nó báo kết nối adb thành công. Bây giờ ta có thể thực hiện chạy ứng dụng lên thiết bị thật thông qua trạm phát WIFI này (đỡ phải chạy máy ảo rất nặng tốn bộ nhớ) và không phải rườm rà dây rợ lung tung. Ở khoảng cách xa vẫn kết nối được, Tui đã thử 30 mét vẫn OK. Bạn thử đi xa 1km xem thế nào(Tui không đi đâu)…. Chú ý là bạn có thể đóng màn hình này lại nhé, không phải mở nó mãi mãi.

Và bạn nên đưa nó ra làm Shortcut ngoài desktop để mỗi lần hết kết nối thì cứ bấm kết nối lại là xong, rất là nhanh, chỉ cần double click vào nó (chú ý là cứ double click đến khi nào nó báo thành công như vậy, vì đôi khi nó có vấn đề gì đó về đường truyền…).

Bước 6:

Sử dụng.

Bây giờ mỗi lần từ Eclipse bạn thực thi ứng dụng nó sẽ tự động tìm kiếm đúng trạm phát đó và cho phép mình xác nhận để chạy lên máy thật. Nếu bạn muốn Demo khi báo cáo thì bạn nên tải phần mềm “droidAtScreen-1.1.jar” (chỉ cần bấm vào để chạy không cần setup) vào PC.

Đây là kết quả tui tải về và chạy lên, nó tự động hiển thị luôn màn hình thiết bị thật của tui vào Desktop PC thông qua chương trình này (chú ý là bạn không cần cắm cáp USB hay kết nối internet nhé, chỉ sử dụng qua trạm phát WIFI):

android_49_22

Bạn thử làm lại nhé…..

(chú ý là cứ bấm file bat đến khi nào nó báo thành công như hình Tui chụp, vì đôi khi không phải bấm cái là kết nối thành công.)

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

Bài 8: Sử dụng Textblock, Textbox và Button trong Windows phone


Trong bài tập này Tui sẽ trình bày về 3 control cơ bản nhất mà một ứng dụng Windows phone thường sử dụng, đó là:

Textblock - Hiển thị dữ liệu không cho chỉnh sửa (giống như Label nhưng mà nó cao thủ hơn 1 tí)

Textbox - Hiển thị và cho phép hiệu chỉnh dữ liệu

Button - Control cho phép người sử dụng tương tác ra lệnh cho ứng dụng.


Textblock có các thuộc tính thường sử dụng như: font chữ (FontFamily), cỡ chữ (FontSize), màu chữ (Foreground), kiểu chữ (FontStyle), in đậm in nghiêng (FontWeight)…

Textblock có thể giúp ta định dạng riêng cho từng vùng dữ liệu thông qua đối tượng Run, hay định dạng xuống dòng thông qua đối tượng LineBreak.

ví dụ ta khai báo XAML như sau:


<TextBlock FontFamily="Arial" FontWeight="Bold">
<Run FontFamily="Courier New">
drthanh là ai?
</Run>
<LineBreak/>
<Run FontFamily="Time New Roman" Foreground="Yellow">
chắc là ông Doctor
</Run>
<LineBreak/>
<Run FontFamily="Verdana" FontSize="40">
với ông Thanh
</Run>
</TextBlock>

Kết quả:

wp8_1Hoặc ta cũng có thể viết coding behind thông qua Inlines của Textblock:

Ví dụ Tui có dùng Textblock để hiện thị màu ngẫu nhiên cho từng từ dưới đây:

wp8_2


string str="... Anh em không hòa, bạn bè vô ích";

string []arr= str.Split(new char[]{' '},  StringSplitOptions.RemoveEmptyEntries);

txtThu.Text = "";//là Textblock trên giao diện bạn đặt tên

Random rd = new Random();

foreach (string s in arr)

{

int red = rd.Next(0, 255);

int green = rd.Next(0, 255);

int blue = rd.Next(0, 255);

Color mau = new Color();

mau.R = (byte)red;

mau.G = (byte)green;

mau.B = (byte)blue;

mau.A = 255;

SolidColorBrush br = new SolidColorBrush(mau);

Run r = new Run();

r.Text = s + " ";

r.Foreground = br;

txtThu.Inlines.Add(r);

}


 

Textbox - Hiển thị và cho phép hiệu chỉnh dữ liệu:

Textbox cung cấp hàng loạt các properties như sau:

  • Name – tên của textbox dùng cho việc tương tác trong coding
  • Text – dùng để hiển thị dữ liệu
  • SelectedText – dữ liệu được chọn trong textbox
  • IsReadOnly – kiểm tra xem textbox chỉ cho đọc hay không
  • MaxLength – chiều dài tối đa
  • TextAlignment: Center|Left| Right| Justify  – các căn lề : Giữa, trái , phải, đều 2 bên.
  • InputScope : Hiển thị loại Keyboard thích hợp cho từng loại, ví dụ như Number, số điện thoại

wp8_5Một số Keyboard phổ biến:

wp8_6

  • AcceptsReturn , TextWrapping – cho phép hiển thị dữ liệu nhiều dòng giống như TextArea. Ta cần thiết lập AcceptsReturn=”True”TextWrapping=”Wrap” 

<TextBox AcceptsReturn="True" TextWrapping="Wrap" Height="150" Text="This is text that will appear on several lines. This will also handle carriage returns." />

 

wp8_3

Cùng các phương thức:

  • Select(start, length): chọn các ký tự từ vị trí start với số lượng ký tự chọn là length
  • SelectAll() : Chọn tất cả chuỗi

wp8_4Ngoài ra trong bộ Windows phone toolkit có hỗ trợ PhoneText control có thuộc tính Hint giúp gợi ý chức năng sử dụng rất hữu ích. Ở bài 7 Tui có nói phần sử sụng WrapPanel  thuộc Windows phone toolkit là bạn đã tải nó về, bạn có thể vào xem thư mục chứa nó (khi bạn tả về tự nó phát sinh theo version mới nhất):

wp8_7Trong thư mục WP8 bạn sẽ tìm thấy thư viện Microsoft.Phone.Controls.Toolkit.dll (Ta sao chép thư viện này tới 1 nơi nào đó để cất giữ cho các lần sử dụng khác, không quan tâm tới các thành phần còn lại). Như trước Tui đã nói chỉ cần tải 1 lần duy nhất, các lần sau chỉ cần tham chiếu tới dll này mà thôi, ví dụ:

- Bấm chuột phải vào References/ chọn Add Reference…

wp8_8

Màn hình Reference Manager hiển thị ra như dưới đây, ta chọn mục Browser/ Browser…:

wp8_9Sau khi bạn bấm vào nút Browse… sẽ hiển thị màn hình Select the files to Reference….:

wp8_10Ở màn hình trên bạn tìm tới nơi cất giữ thư viện toolkit, bấm chọn nó rồi bấm nút Add/ nó quay về màn hình Reference Manager:

wp8_11Ta tick chọn thư viện như hình rồi bấm nút OK. Kết quả sẽ thấy được trong Reference của Project như sau:

wp8_12Sau đó ta cũng khai báo sử dụng namespace như trước:

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

Rồi sử dụng PhoneText control như sau:


        <toolkit:PhoneTextBox Hint="nhập hint ở đây"
                              InputScope="Number">
            
        </toolkit:PhoneTextBox>

 

wp8_13Bạn có thể sử dụng control này thay thế cho Textbox.


Button - Control cho phép người sử dụng tương tác ra lệnh cho ứng dụng, đây là một control thường xuyên xuất hiện trong ứng dụng.


<Button
x:Name="btnClickMe"
Content="Click tui đi"
Width="300"
Height="100"
FontFamily="cambria"
FontSize="35"
Foreground="Yellow">

</Button>

Kết quả:

wp8_14Để gán sự kiện cho Button ta có một số cách sau:

- Gán lúc Designer time (lúc trong quá trình thiết kế giao diện).

- Gán lúc Runtime (lúc đang chạy ứng dụng).

Nếu gán lúc Designer time thì có 3 cách tạo sự kiện cơ bản sau:

- 1 là bạn double click vào Button để phát sinh sự kiện trong xaml.cs:

Sự kiện click sẽ tự động được gán cho Button btnClickMe ở trên, thường thao thác này hơi rắc rối do đôi khi bạn double click nó không “ăn”:


private void btnClickMe_Click(object sender, RoutedEventArgs e)
{

}

-2 là bạn viết sự kiện bằng cách gõ trong tag xml của Button, ví dụ Tab, click….:

Ví dụ Tui bổ sung sự kiện Tab cho Button btnClickMe trong xaml bằng cách gõ bằng tay như sau:

wp8_15Khi bạn gõ Tap= thì lập tức “<New Event Handler>” hiển thị ra bạn bấm chọn nó thì sự kiện Tap sẽ tự động được phát sinh (tương tự cho các sự kiện khác mà bạn có thể làm theo cách này):

Trong XAML:


<Button
x:Name="btnClickMe"
Content="Click tui đi"
Width="300"
Height="100"
FontFamily="cambria"
FontSize="35"
Foreground="Yellow"
Click="btnClickMe_Click"
Tap="btnClickMe_Tap"
>

</Button>

Trong Code Behind:


private void btnClickMe_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{

}

-3 là bạn sử dụng công cụ Propeties, trong công cụ này có biểu tượng tia chớp để gán sự kiện cho control.

Ví dụ Tui bổ sung sự kiện Double Tap cho Button btnClickMe bằng cách chọn trong Properties toolbox như sau:

Chọn Button (hoặc control bất kỳ), mở Properties/ chọn biểu tượng Tia chớp (mục số 1)/ rồi bạn Double click vào mục số 2 tương ứng với sự kiện bạn nhìn thấy và mong muốn sử dụng ở mục số 1 là tự động nó phát sinh sự kiện:

wp8_16Giờ Tui double click vào mục số 2 tương ứng với sự kiện DoubleTap thì ta có kết quả sau:

wp8_17Tự nó phát sinh ra trong XAML (hình trên) và Coding behind như sau:


private void btnClickMe_DoubleTap(object sender, System.Windows.Input.GestureEventArgs e)
{

}

Như vậy cho dù làm cách nào đi nữa thì sự kiện phải xuất hiện 2 nơi: Đó là nằm trong XAML và nằm trong Coding behind.

- Nếu Gán sự kiện lúc Runtime (lúc đang chạy ứng dụng) :

Tui sẽ làm một ví dụ tạo Button và gán sự kiện trong lúc Runtime để demo cho trường hợp này như sau( trường hợp này cũng thường xuyên được sử dụng trong project):

Bạn new 1 project tên là “LearnAddButtonAtRuntime“:

Khi tạo mới project này thì mặc định MainPage.xaml được tạo ra và bạn tìm tới XAML giống thế này trong trang:


<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

</Grid>

Bạn để ý tên “ContentPanel“, bây giờ Tui sẽ coding để thực hiện thêm một số Button có Content ngẫu nhiên vào phần này sau đó gán sự kiện Rumtime cho nó, bây giờ bạn vào MainPage.xaml.cs tạo 1 hàm tạo Button ngâu nhiên 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 LearnAddButtonAtRuntime.Resources;

namespace LearnAddButtonAtRuntime
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
//gọi hàm tạo button lúc Runtime
TaoButtonRuntime();
}
public void TaoButtonRuntime()
{
//xóa hết control cũ nằm bên trong ContentPanel
ContentPanel.Children.Clear();
Random rd = new Random();
//Tạo StackPanel
StackPanel pn = new StackPanel();
for(int i=0;i<10;i++)
{
Button btn = new Button();
btn.Content = rd.Next(0, 100);
btn.Width = btn.Height = 100;
//gán sự kiện động cho Button btn:
//bạn chỉ cần gõ tên control.sự kiện rồi gõ dấu += sau đó gõ 2 phím tab liên tục--> tự tạo ra sự kiện
btn.Tap += btn_Tap;
//Đưa control vào StackPanel
pn.Children.Add(btn);
}
//Tạo ScrollViewer
ScrollViewer scv = new ScrollViewer();
scv.Height = 500;
//Đưa stack vào ScrollViewer
scv.Content = pn;
//đưa ScrollViewer vào ContentPanel
ContentPanel.Children.Add(scv);
}

void btn_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
//sender chắc chắn là Button nên ta ép kiểu về Button để xử lý
Button btn = sender as Button;
MessageBox.Show("Bạn chọn button có giá trị ="+btn.Content);
}
}
}

Kết quả:

wp8_18

Bây giờ Tui sẽ làm một bài ví dụ nho nhỏ để sử dụng tổng thể Textblock, Textbox và Button như sau:

Tạo một Project đặt tên “LearnChuyenNamDuongLichThanhAmLich“.

 XAML code:


<phone:PhoneApplicationPage
x:Class="LearnChuyenNamDuongLichThanhAmLich.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">
<Border  BorderThickness="5" Margin="0,0,0,481">
<Border.BorderBrush>
<LinearGradientBrush>
<GradientStop Color="Red" Offset="0.0"></GradientStop>
<GradientStop Color="Yellow" Offset="0.5"></GradientStop>
<GradientStop Color="Blue" Offset="1.0"></GradientStop>
</LinearGradientBrush>
</Border.BorderBrush>
<Canvas HorizontalAlignment="Left" Height="768" VerticalAlignment="Top" Width="480">

<TextBlock Canvas.Left="51" TextWrapping="Wrap" Text="Năm Dương:" Canvas.Top="78"/>
<TextBox x:Name="txtNamDuong" Height="72" Canvas.Left="179" TextWrapping="Wrap" Text="1978" Canvas.Top="57" Width="237" InputScope="Number"/>
<Button x:Name="btnChuyenDoi" Content="Chuyển đổi" Canvas.Left="179" Canvas.Top="134" Click="btnChuyenDoi_Click"/>
<TextBlock Canvas.Left="51" TextWrapping="Wrap" Text="Năm âm:" Canvas.Top="220"/>
<TextBlock x:Name="txtNamAm" Canvas.Left="192" TextWrapping="Wrap" Canvas.Top="220" Width="212" Height="42"/>
<TextBlock Canvas.Left="10" TextWrapping="Wrap" Text="Chuyển đổi năm dương lịch" Canvas.Top="10" Width="460" Height="45" TextAlignment="Center" FontSize="30"/>
</Canvas>
</Border>

</phone:PhoneApplicationPage>

Coding Behind:


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 LearnChuyenNamDuongLichThanhAmLich.Resources;

namespace LearnChuyenNamDuongLichThanhAmLich
{
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
string[] cans = {"Canh","Tân","Nhâm","Quý","Giáp","Ất","Bính","Đinh","Mậu","Kỷ" };
string[] chis = {"Thân","Dậu","Tuất","Hợi", "Tý","Sửu","Dần","Mẹo","Thìn","Tỵ","Ngọ","Mùi"};
private void btnChuyenDoi_Click(object sender, RoutedEventArgs e)
{
int nam = int.Parse(txtNamDuong.Text);
string can = cans[nam % 10];
string chi = chis[nam % 12];
txtNamAm.Text = can + " " + chi;
}
}
}

Kết quả:

wp8_19

Bạn có thể bấm vào đây để tải source mẫu

Như vậy các bạn đã nắm rõ được các control Textblock, Textbox, Button, cách tham chiếu sử dụng Windows Phone toolkit có sẵn…

Trong bài kế tiếp Tui sẽ trình bày về RadioButton, CheckBox … các bạn chú ý theo dõi.

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

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.

Bài 6: Xây dựng giao diện với XAML trong Windows Phone (phần 3)


Phần này Tui sẽ nói về Cách sử dụng Resource và Style.

Trong quá trình xây dựng ứng dụng, chắc chắn ta sẽ không tránh khỏi yêu cầu làm thế nào để ứng dụng của ta mang một style thống nhất, ví dụ những màu chữ, kiểu chữ, font chữ trên các trang phải đồng nhất với nhau. Ngoài ra, ta còn phải làm việc với một số control đòi hỏi phải định dạng trước mẫu dữ liệu mà control đó sẽ hiển thị, ví dụ như ListBox hay LongListSelector. Và ta cũng cần tách biệt giữa code định dạng các control và code khai báo các control để tài nguyên được trong sáng và dễ chỉnh sửa hơn, có thể tái sử dụng được nhiều lần. Để giải quyết các vấn đề trên, ta cần sử dụng các style và resource được cung cấp trong Windows Phone.

Resource sẽ được chia thành 2 nhóm chính đó là Style DataTemplate.

Ta sử dụng Style để định dạng, trang trí cho các control, còn DataTemplate dùng để định nghĩa mẫu dữ liệu cho các list control (Listbox, LonglistSelector)

Style: Để định nghĩa một style, ta khai báo cú pháp XAML như sau:

<Grid.Resources >
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="Height"   Value="100" />
<Setter Property="Width"   Value="200"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Background" Value="BlueViolet"/>
</Style>
 </Grid.Resources>

- Thuộc tính x:Key dùng để định danh cho style

- Thuộc tính TargetType dùng để loại control sẽ được áp dụng

Lưu ý: nếu thuộc tính x:Key không được khai báo thì tất cả các control cùng loại với TargetType sẽ được áp dụng style.

- Một thẻ <Setter/> sẽ khai báo cho một thuộc tính của control

- Để áp dụng 1 style cho 1 control ta khai báo thuộc tính Style của control đó như sau:

Style=”{StaticResource <tên của style>} “

Tức là ta có thể sử dụng như sau:

<Button Style=”{StaticResource  ResourceKey=buttonStyle}”  Content= “drthanh”/>

Kết quả:

wp6_27Đặc biệt ta cũng có thể kế thừa Style theo cách sau:

wp6_28

DataTemplate: để định dạng DataTemplate, ta cũng định dạng giống như khi định dạng ItemTemplate cho các control.

VD: Định nghĩa một DataTemplate:


<DataTemplate x:Key="ListBoxTemplate">

<StackPanel>

<TextBlock Text="Name"/>

<TextBlock Text="{Binding Path=Name}"/>

<TextBlock Text="Surname"/>

<TextBlock Text="{Binding Path=Surname}"/>

</StackPanel>

</DataTemplate>

- Thuộc tính x:Key dùng để định danh cho DataTemplate.

Ta cũng có thể khai báo dạng ControlTemplate:

wp6_29Hoặc tách rời controltemplate ra:

wp6_30Bây giờ Tui sẽ nói về các vị trí đặt Resource:

Có 3 vị trí:

- Đặt ở Page Resource

  • Được khai trong một trang XAML và chỉ được sử dụng trong trang đó.
  • Được định nghĩa trong cặp thẻ:

<phone:PhoneApplicationPage.Resources>

<!-- Định nghĩa các Resource tại đây -->

</phone:PhoneApplicationPage.Resources>

- Đặt ở Application Resource

  • Được khai trong một trang App.xaml và toàn bộ các trang trong ứng dụng đều có thể sử dụng
  • Được định nghĩa trong cặp thẻ:

<Application.Resources>

<!-- Định nghĩa các Resource tại đây -->

</Application.Resources>

- Đặt trong Dictionary Resource

  • Được khai báo trong một file xml riêng lẻ
  • Tên file phải được kết thúc bằng “.xaml
  • Các Resource được định nghĩa trong cặp thẻ:

<?xml version="1.0" encoding="utf-8" ?>

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

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

<!--Định nghĩa các Resource tại đây -->

</ResourceDictionary>

  • Để sử dụng, ta add vào Application Resource hoặc Page Resource như sau:

<Application.Resources>

<ResourceDictionary>

<local:LocalizedStrings xmlns:local="clr-namespace:Demo_Brush_Resource" x:Key="LocalizedStrings"/>

<ResourceDictionary.MergedDictionaries>

<ResourceDictionary Source="Assets/Resources/Style.xaml"/>

</ResourceDictionary.MergedDictionaries>

</ResourceDictionary>

</Application.Resources

Chi tiết cho việc tạo Dictionary Resource:

- Bước 1: Tạo một Project tên LearnResource

- Bước 2: Thêm 1 Dictionary Resource

Bấm chuột phải vào Project chọn Add/New Item:

wp6_31

Chú ý mặc định là xml bạn tự gõ thành .xaml

Sau đó tiến hành viết nội dung cho MyResource.xaml như hình dưới đây:

wp6_32


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

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

<LinearGradientBrush x:Key="drthanhbrush">

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

<GradientStop Color="Blue" Offset=".7" />

</LinearGradientBrush>

</ResourceDictionary>

- Bước 3- Đưa vào Application Resource trong App.xaml.

 Mở App.xaml:


<Application.Resources>

<ResourceDictionary>

<ResourceDictionary.MergedDictionaries>

<ResourceDictionary Source="MyResource.xaml"/>

</ResourceDictionary.MergedDictionaries>

<local:LocalizedStrings

xmlns:local="clr-namespace:LearnResource"

x:Key="LocalizedStrings"/>

</ResourceDictionary>

</Application.Resources>

- Bước 4- sử dụng Application Resource trong 1 trang XAML nào đó, ví dụ (MainPage.xaml):


<Button Background="{StaticResource ResourceKey=drthanhbrush}"

Content="drthanh"/>

Trong Dictionary resource Tui có để key là drthanhbrush, thì ở chỗ sử dụng sẽ dùng key này.

Như vậy bạn đã biết cách tạo Dictionary Resource và cách sử dụng nó.

Bạn chú ý tag:

<ResourceDictionary.MergedDictionaries>

Là nơi cho phép chúng ta sử dụng nhiều file Dictionary Resource, ví dụ tập các style dành cho Textblock lưu 1 dictionary riêng, tập các style danh cho Button lưu 1 dictionary riêng…. cuối cùng ta gom chung lại sử dụng trong ứng dụng.

Khi sử dụng Dictionary thì ta nên đưa vào Application Resource để mọi nơi trong ứng dụng đều có thể truy suất.

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

Bài 6: Xây dựng giao diện với XAML trong Windows Phone (phần 2)


Tiếp tục trình bày về Xây dựng giao diện với XAML, ở phần 2 này Tui sẽ nói về cách sử dụng Brush.

Phần 2) Cách sử dụng Brush

Brush là một công cụ giúp ta định nghĩa màu cho các control. Brush hỗ trợ ta vẽ màu đơn sắc và kết hợp nhiều màu với nhau theo kiểu Gradient. Dưới đây là một số brush được hỗ trợ trong Windows Phone:

wp6_13Tui chụp một số màu đại diện tương ứng để bạn dễ liên tưởng:

wp6_14Để tạo một đối tượng Brush thì ta có thể sử dụng XAML để định nghĩa hoặc sử dụng coding behind, tùy từng trường hợp mà ta nên sử dụng một cách khéo léo.

Để định nghĩa một Brush, ta có thể định nghĩa trực tiếp trên code XAML hoặc định nghĩa trong code behind. Và ta cần cần biết cách viết chuyển đổi qua lại giữa coding behind và XAML.

Ứng với mỗi loại Brush Tui sẽ viết bằng 2 cách (coding behind và XAML) để các bạn có thể dễ dàng hiểu được cách sử dụng Brush cũng như cách viết chuyển đổi.

Đa phần các Brush nằm trong thư viện:

using System.Windows.Media

1)SolidColorBrush:

Dùng để tạo màu đơn sắc đồng nhất (Ví dụ màu đỏ, màu xanh, màu vàng).

Cách tạo trong XAML:


<Button Content="drthanh" >

    <Button.Background>

        <SolidColorBrush Color="Red">

        </SolidColorBrush>

    </Button.Background>

</Button>

 

wp6_15Cách tạo trong coding behind:

Nếu màu đơn sắc đó là màu phải dựa theo những thông số RED, GREEN, BLUE ta làm như sau


Color cr = new Color();

cr.B = cr.R = cr.G = 122;

cr.A = 255;

SolidColorBrush br = new SolidColorBrush(cr);

button1.Background = br;

 

ở trên Tui để cr.B=cr.R=cr.G=122 , bạn có thể tách riêng ra mỗi dòng để gán mỗi giá trị riêng biệt cho nó.

Nếu như màu đơn sắc chỉ lấy màu theo hệ thống đã định nghĩa thì ta làm như sau:


SolidColorBrush br = new SolidColorBrush(Colors.Blue);

button1.Background = br;

 

Để giúp các bạn dễ dàng tìm được các thông số RED, GREEN, BLUE để tạo màu cho đối tượng, tui có viết sẵn công cụ lấy màu theo các thông số này, bạn có thể tải ở đây: Link Download

wp6_16Bạn chỉ cần kéo thả trackbar để chọn màu và các giá trị RED, GREEN, BLUE sẽ xuất hiện theo. hoặc bấm vào button “…” để hiển thị cửa sổ chọn màu:

wp6_172)LinearGradientBrush:

Dùng để tạo bảng phối màu theo dạng tuyến tính, các bạn khi làm màu Gradient thì chú ý về cơ chế hoạt động của nó là: Không quan tâm tới kích thước của cửa sổ là bao nhiêu (tức là nếu 1 đối tượng có kích thước là 500×500 với 1 đối tượng có kích thước là 50×50 là như sau), nó chỉ quan tâm góc trái trên cùng là (0.0,0.0) và góc phải cuối cùng là (1.0,1.0) đây là một dãy số thực vô hạn:

wp6_18Cách tạo trong XAML:

<Button Content= "drthanh" name="btnLinear">
                <Button.Background>
                    <LinearGradientBrush StartPoint="0.75,0.25">
                        <GradientStop Color="Red" Offset="0.0"/>
                        <GradientStop Color="Blue" Offset="0.5"/>
                        <GradientStop Color="White" Offset="1.0"/>
                    </LinearGradientBrush>
                </Button.Background>
            </Button>

 

Cách tạo trong coding behind:


public MainPage()
{
InitializeComponent();

LinearGradientBrush brush=new LinearGradientBrush();
brush.StartPoint=new Point(0.75,0.25);
GradientStop st1=new GradientStop();
st1.Color=Colors.Red;
st1.Offset=0.0;

GradientStop st2=new GradientStop();
st2.Color=Colors.Blue;
st2.Offset=0.5;

GradientStop st3=new GradientStop();
st3.Color=Colors.White;
st3.Offset=1.0;

brush.GradientStops.Add(st1);
brush.GradientStops.Add(st2);
brush.GradientStops.Add(st3);

btnLinear.Background = brush;

}

Kết quả:

wp6_20Bạn để ý thông số Offset là vị trí trong đoạn (0.0,1.0) mà ta bắt đầu đổ màu vào, bạn cứ tưởng tượng là 1 tờ giấy A4 được bạn đổ một bình mực vào vị trí nào, nơi nào được đổ vào trước thì ở đó đậm nét của màu và lan tỏa ra xung quanh, màu nào mạnh hơn thì chiếm ưu thế hơn.

Tiếp tục quan sát StartPoint có 2 thông số (X,Y) là điểm khởi đầu tô màu cho màu đầu tiên trong danh sách màu, ở trên ta thấy màu đỏ được tô bắt đầu từ tọa độ X=0.75, Y=0.25 nên có hình dáng như vậy.

Nếu như bạn phối 4 màu:

Yellow có Offset 0.0

Red có Offset 0.25

Blue có Offset 0.75

LimeGreen có Offset 1.0

Thì có có bảng phân bố màu như sau:

wp6_212)RadialGradientBrush:

Phối màu theo hình cầu có tiêu điểm

wp6_22Cách viết XAML:


<Rectangle Width="200" Height="100">

<Rectangle.Fill>

<RadialGradientBrush

GradientOrigin="0.5,0.5"

Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">

<RadialGradientBrush.GradientStops>

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

<GradientStop Color="Red" Offset="0.25" />

<GradientStop Color="Blue" Offset="0.75" />

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

</RadialGradientBrush.GradientStops>

</RadialGradientBrush>

</Rectangle.Fill>

</Rectangle>

Cách viết trong Coding behind:


RadialGradientBrush radialGradient = new RadialGradientBrush();

// thiết lập GradientOrigin để vẽ tâm bẻ góc (làm lệch tâm) của bảng màu.

radialGradient.GradientOrigin = new Point(0.5, 0.5);

// Thiết lập tọa độ tâm.

radialGradient.Center = new Point(0.5, 0.5);

// Thiết lập bo góc.

radialGradient.RadiusX = 0.5;

radialGradient.RadiusY = 0.5;

// Tạo 4 màu phối lại với nhau

radialGradient.GradientStops.Add(new GradientStop(Colors.Yellow, 0.0));

radialGradient.GradientStops.Add(new GradientStop(Colors.Red, 0.25));

radialGradient.GradientStops.Add(new GradientStop(Colors.Blue, 0.75));

radialGradient.GradientStops.Add(new GradientStop(Colors.LimeGreen, 1.0));

// Freeze the brush (make it unmodifiable) for performance benefits.

radialGradient.Freeze();

// Tạo một Rectangle (bạn có thể lấy tên của một control nào đó)

Rectangle aRectangle = new Rectangle();

aRectangle.Width = 200;

aRectangle.Height = 100;

aRectangle.Fill = radialGradient;

Bạn cần lưu ý các  thuộc tính như GradientOrigin, Center, RadiusX, RadiusY. Hình sau mô tả công năng từng thuộc tính:

wp6_23Ví dụ:


<Button x:Name="button1" Content="drthanh" >
<Button.Background>
<RadialGradientBrush GradientOrigin="0.75,0.25" RadiusX="0.3" RadiusY="0.5">
<GradientStop Color="Yellow" Offset="0.0"/>
<GradientStop Color="Orange" Offset="0.5"/>
<GradientStop Color="Blue" Offset="1.0"/>
</RadialGradientBrush>
</Button.Background>
</Button>

wp6_244) ImageBrush:

ImageBrush cho phép hiển thị hình ảnh.

wp6_25Nếu viết lại trong coding behind:


using System.Windows.Media;

using System.Windows.Media.Imaging;

....

ImageBrush br = new ImageBrush();

br.ImageSource = new BitmapImage

(

new Uri(

"Assets\\hinhvui.PNG",

UriKind.Relative)

);

btnimg.Background = br;

wp6_26Như vậy Tui đã trình bày sơ qua về một số Brush thường sử dụng, bạn có thể sử dụng để vận dụng vào các bài tập tiếp theo.

Bài tiếp theo Tui sẽ nói về phần số 3 Cách sử dụng Resource và Style.

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

Bài 6: Xây dựng giao diện với XAML trong Windows Phone (phần 1)


Từ bài 1 ->bài 5 các bạn đã biết được cách thức tạo 1 Project Windows phone, cách sử dụng Emulator, đăng ký lập trình với thiết bị thật cũng như hiểu được vòng đời của một ứng dụng Windows phone như thế nào.

Từ Bài 6 trở đi Tui sẽ hướng dẫn các bạn cách thức lập trình với Windows Phone 8.1 Silverlight, Tui sẽ cố gắng tách từng phần nhỏ theo thứ tự từ dễ lên khó để giúp các bạn dễ nắm bắt cũng như có thể tự xâu chuỗi lại thành một hệ thống để có thể tiến hành viết được trọn vẹn một ứng dụng thực tế nào đó.

Trên internet có rất nhiều website hướng dẫn lập trình về Windows Phone 8.1 Silverlight các bạn có thể tham khảo,  tuy nhiên Tui sẽ hướng dẫn theo cách của Tui các bạn có thể chấp nhận hoặc không chấp nhận, nhưng dù sao các bạn cũng phải hiểu được căn cơ của Windows Phone 8.1 thì mới bắt tay lập trình tốt được, không quan trọng là đọc trang nào.

Phần Xây dựng giao diện với XAML trong Windows Phone tui sẽ trình bày thành 4 bài độc lập như sau:

Phần 1) Cách thức làm việc với XAML

Phần 2) Cách sử dụng Brush

Phần 3) Cách sử dụng Resource và Style

Các bạn cần hiểu XAML trong Windows Phone vì khi bắt đầu new 1 project Helloworld là bạn để nhìn thấy ngay cấu trúc XAML của Windows Phone rồi. Nếu bạn đã có kiến thức về XML thì XAML cũng có vẻ tương tự nhưng võ công cao hơn 1 bậc.

Windows Phone sử dụng  XAML làm đặc thù cho phần thiết kế giao diện, bạn có thể sử dụng trực tiếp Visual Studio hoặc công cụ Microsoft Expression Blend để thiết kế (thường trong quá trình cài đặt Visual Studio nó đã đính kèm công cụ này rồi).

Bây giờ ta bắt đầu tìm hiểu XAML với phần đầu tiên:

Phần 1) Cách thức làm việc với XAML

  • XAML là gì?

-XAML (Extensible Application Markup Language) – phát âm zammel.

XAML là một ngôn ngữ đánh dấu khai báo tương tự như XML, nó được sử dụng để tạo giao diện tương tác với người dùng. Mỗi một phần tử trong XAML (tag element) đại diện cho một đối tượng (Object). XAML giúp ta trực quan hóa giao diện cũng như có khả năng lưu trữ hiển thị Data Source cũng như Custom Object. Bạn có thể để ý là mỗi một Project bạn tạo ra đều có một file MainPage.xaml đó chính là màn hình khởi động mặc định khi chạy ứng dụng cho phép người sử dụng tương tác.

Microsoft đã tách thành 2 phần riêng biệt: Phần xaml để thiết kế phần xaml.cs để lập trình (có thể gọi là logic runtime) giúp ta nâng cao khả năng tùy biến các control. Bạn có thể tưởng tượng rằng XAML thực chất là một định dạng XML mà thôi (Có phần mở rộng là .xaml).

Ví dụ về trang MainPage.xaml:


&lt;phone:PhoneApplicationPage

x:Class=&quot;LearnXAML.MainPage&quot;

xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;

FontFamily=&quot;{StaticResource PhoneFontFamilyNormal}&quot;

FontSize=&quot;{StaticResource PhoneFontSizeNormal}&quot;

Foreground=&quot;{StaticResource PhoneForegroundBrush}&quot;

SupportedOrientations=&quot;Portrait&quot; Orientation=&quot;Portrait&quot;

shell:SystemTray.IsVisible=&quot;True&quot;&gt;

…

&lt;/phone:PhoneApplicationPage&gt;

  •  XAML Namespace?

Thường mỗi trang XAML có khai báo các namespace với một prefix ngắn gọn mang tính gợi nhớ để giúp Ta dễ dàng lập trình cũng như truy suất các thông tin trong namespace.

Theo Tui thì có 2 lý do chính để chúng ta tạo namespace và đặt prefix name cho Namespace:

- Do tên Namespace quá dài và phức tạp.

- Do có nhiều lớp trùng tên nên cần đưa vào các Namespace khác nhau.

Việc sử dụng prefix (có thể hiệu đại khái là tên gì đó ngắn gọn đại diện cho Namespace) sẽ giúp chúng ta lập trình nhanh chóng.

Nếu quan sát kỹ ngay trang MainPage.xaml là bạn có thể phát hiện ra cách khai báo sử dụng namespace, prefix:

wp6_1Ta có cú pháp như sau:

wp6_2xmlns là từ khóa (tức là phải viết y xì vậy đó)

clr-namespace là từ khóa (tức là phải viết y xì vậy đó)

local là prefix (tức là tên ta muốn đặt đại diện cho CLR Namespace Name), thường thì ta nên đặt mang tính gợi nhớ.

Bạn phải nhớ công thức này để qua các bài tập tiếp theo Tui sẽ sử dụng lại (cụ thể trong việc sử dụng thư viện Windows Phone Toolkit)

Sau đây Tui sẽ làm một ví dụ về cách tạo 2 lớp MyButton (tức là cùng tên) nhưng nằm ở 2 namespace khác nhau, sau đó Tui sẽ minh họa cách sử dụng 2 MyButton này với công thức ở trên.

Lớp MyButton thứ nhất (mặc định có nền đỏ) tui cho nó nằm trong namespace tên tranduythanh.com, Lớp MyButton thứ nhì (mặc định có màu Xanh) tui cho nó nằm trong namespace caphe.net.

Tức là 2 MyButton này tui sẽ kế thừa từ Button của Microsoft và hiệu chỉnh lại theo thông số mà tui mô tả ở trên.

Bạn new một Project tên LearnNamespace:

wp6_3Bạn thấy ở trên Tui tô xanh file MyButton.cs (File này sẽ chứa 2 class MyButton nằm ở 2 Namespace khác nhau), bạn tạo file này như sau:

- Bấm chuột phải vào Project/ Chọn Add/ Class…:

wp6_4Màn hình Add New Item hiển thị ra như bên dưới, bạn chọn Class ở mục số 1, rồi đặt tên cho tập tin là MyButton ở mục số 2, sau đó bấm nút Add để tạo file này.

wp6_5Sau khi tạo xong bạn Double click vào MyButton.cs để tiến hành coding như sau:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

//thêm thư viện này để kế thừa Button
using System.Windows.Controls;
//Thêm thư viện này để sử dụng SolidColorBrush
using System.Windows.Media;

namespace tranduythanh.com
{
public class MyButton:Button
{
public MyButton()
{
SolidColorBrush brush = new SolidColorBrush(Colors.Red);
this.Width = 400;
this.Height = 200;
this.Background = brush;
}
}
}
namespace caphe.net
{
public class MyButton:Button
{
public MyButton()
{
SolidColorBrush brush = new SolidColorBrush(Colors.Blue);
this.Width = 300;
this.Height = 100;
this.Background = brush;
}
}
}

Bạn thấy đấy ở trên có 2 MyButton trùng tên nhưng nằm ở 2 namespace khác nhau.

Để sử dụng 2 lớp MyButton này ta tiến hành biên dịch Project–> 2 MyButton này sẽ tự động được đưa vào thanh Toolbox và bạn chỉ việc dùng chuột túm kéo thả nó vào giao diện Windows Phone là OKê.

wp6_6Bây giờ bạn kéo thả MyButton (tranduythanh.com) và MyButton (caphe.net) vào giao diện Windows Phone (giống như là kéo 1 control bất kỳ), ta xem kết quả:

wp6_7Bạn quan sát hình trên:

- Mục số 1 là nơi mà 2 MyButton được Khai sinh ra trên cõi đời này sau khi bạn Build project.

- Mục số 2 là nơi mà bạn kéo thả 2 MyButton này vào (quan sát thấy màu và kích thước mặc định được tạo trong Constructor)

- Mục số 3: Là cách khai báo sử dụng Namespace được hệ thống tự động tạo ra (trong trường hợp này nó sẽ tự động lấy cái thành phần cuối cùng đằng sau dấu chấm “.” làm prefix, ví dụ: tranduythanh.com thì lấy com, caphe.net thì lấy net. Dĩ nhiên không phải trường hợp nào nó cũng tự động tạo ra cho ta như thế này mà có những trường hợp ta phải tự gõ theo công thức (đề cập ở phần trên).

- Mục số 4 là nơi mà XAML coding của MyButton được phát sinh tùy thuộc vào cách bạn thay đổi kích thước cũng như vị trí của nó,  bạn để ý có prefix là com net đằng trước mỗi element MyButton –> truy suất đúng đối tượng nằm trong namespace nào. (Bạn có thể đặt tên prefix khác ).

  •  Các cú pháp XAML Attribute?

Bạn biết rằng XAML tương tự như XML nên cách khai báo đối tượng cũng giống như vậy:

<[Tên thành phần] [Tên thuộc tính]=[giá trị] ></ [Tên thành phần]>

Hoặc

<[Tên thành phần] [Tên thuộc tính]=[giá trị] />

Ví Dụ:

<TextBlock Text=”page name” FontSize =”15″ />

XAML có một số cú pháp được sử dụng để khai báo cho các thuộc tính như sau (Bạn cần biết các thuật ngữ kỹ thuật của nó để dễ đọc tài liệu tiếng anh):

- Object element syntax

- Attribute syntax

- Property Element Syntax

- Attached Property Syntax

- Markup Extensions

Việc nắm rõ từng loại cú pháp giúp ta dễ dàng thiết kế cũng như lập trình. Tui sẽ trình bày và cho ví dụ sơ qua về 5 loại cú pháp thường sử dụng ở trên:

- Object element syntax:

Cú pháp này thường được viết như sau:

<Button> Click Me </Button>

- Attribute syntax:

wp6_8 Bạn xem đấy chỗ nào Attribute là Attribute….. thường ghi các giá trị RẤT ĐƠN GIẢN được gán cho mỗi thuộc tính (Attribute) thì ta sẽ sử dụng Attribute syntax. Tuy nhiên có những trường hợp giá trị của một thuộc tính nào đó lại vô cùng phức tạp phải kết hợp nhiều thông số thì Attribute syntax không còn áp dụng được nữa, mà nó phải sử dụng Property Element Syntax.

- Property Element Syntax:

Khi giá trị phức tạp ta phải sử dụng cú pháp này. Tuy nhiên Tui sẽ đưa ra 2 ví dụ đơn giản và phức tạp để các bạn dễ hình dung:

wp6_9Hay phức tạp phối hợp nhiều màu:

wp6_10Như vậy Ta có thể sử dụng Property Element Syntax cho cả trường hợp đơn giản và phức tạp, tuy nhiên với những trường hợp đơn giản thì không cần thiết vì nó tốn thời gian.

- Attached Property Syntax:

Một số thuộc tính ở element cha được đính kèm vào element con (hoặc ở đâu đó cũng được), ta thường thấy nhất là trong Grid Layout.

wp6_11- Markup Extensions:

- Các giá trị của thuộc tính được đặt trong cặp ngoặc { }. Thường nó được dùng để tham chiếu tới Resource hoặc Binding dữ liệu (ta sử dụng rất nhiều).

wp6_12Như vậy Tui đã trình bay xong Phần 1, qua bài 7 Tui sẽ trình bày về Phần 2) Cách sử dụng Brush. Các bạn nên đọc kỹ và thực hành lại các ví dụ mẫu ở trên để dễ dàng hiểu tiếp các phần còn lại.

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

Bài 5: Vòng đời của ứng dụng Windows phone 8.1 và cách quản lý trạng thái


Trước khi sắn tay áo lập trình thì các bạn cũng cần hiểu được vòng đời của ứng dụng Windows phone và cách quản lý trạng thái của nó như thế nào, vì nêu như không hiểu được vòng đời của ứng dụng thì bạn sẽ gặp khó khăn khi gặp những trường hợp phải lưu cấu hình hệ thống, cũng như không biết vì sao ứng dụng của ta lại tự động mất hay các thông số bị reset….

Khác với Windows Phone 8.0, đối với Windows Phone 8.1 vòng đời của nó được thể hiện như sau (vẽ hình gì cũng được, đại khái là nó như vậy đó). Bạn cũng để ý là Windows Phone 8.0 khi nhấn nút Home rồi bấm nút Back thì nó sẽ không hiển thị lại ứng dụng; Windows Phone 8.1 thì khác nếu 1 ứng dụng đang chạy mà bạn nhấn nút Home sau đó bấm lại nút Back thì ứng dụng đó sẽ được hiển thị trở lại như cũ.

wp5_1- Bạn chú ý rằng với một ứng dụng Windows Phone thì nó có 3 trường hợp chính:

+  Một  là ứng dụng đang chạy (running) –> Người sử dụng quan sát thấy ứng dụng đầy đủ, tương tác được với ứng dụng, và ta cũng có thể gọi nó là Foreground Lifetime

+ Hai là ứng dụng không chạy (terminated)–> Tức là nó không còn sống trên cõi đời của Memory nữa

+ Ba là trạng thái tạm ngưng hoạt động (suspended) –> Ứng dụng vẫn còn sống trên cõi đời của Memory nhưng người sử dụng không tương tác được và nó sẽ bị rơi vào trạng thái Killable (tức là nó có thể bị hệ thống tước đoạt mạng sống bất cứ khi nào–> terminated). Ví dụ như ta đang thao tác với ứng dụng thì tự nhiên có cuộc gọi tới, thì ứng dụng cuộc gọi sẽ đè lên ứng dụng của ta –> ứng dụng của ta chuyển qua suspended.

Bạn cần phải phân biệt rõ trạng thái terminatedsuspended nó khác nhau như thế nào, và phải hiểu được lý do vì sao suspended lại có thể đưa ứng dụng vào trạng thái Killable? nó có một vài lý do chính sau:

1) Hệ thống thiếu RAM và cần thu hồi khi có những yêu cầu khác được ưu tiên hơn

2) Hoặc có thể thiết bị gần hết PIN, hệ thống cần kill ứng dụng để tiết kiệm PIN

3) Hoặc người sử dụng khởi động lại thiết bị.

4) Và những lý do gì đó mà ta không biết…

Khi ứng dụng rơi vào trạng thái Suspended thì nguy cơ nó bị terminated là rất cao, và nếu như không bị terminated thì nó cũng có thể bị reset các biến và đối tượng…

Như vậy một vài câu hỏi đặt ra cho vòng đời là:

1) Ta làm gì khi ứng dụng rơi vào trạng thái Suspended

2) Khi ứng dụng đang thực thi và đang chuyển đổi trạng thái thì các sự kiện gì sảy ra

3) quản lý các trạng thái thay đổi như thế nào.

————————————

Khi viết lệnh quản lý sự thay đổi trạng thái của ứng dụng thì thường ta xử lý ở 2 cấp độ:

- Cấp độ ứng dụng (xử lý trong App.xaml.cs) – có 4 sự kiện chính:


//Sự kiện này sẽ được triệu gọi khi ứng dụng được thực thi và nó sẽ không
//bị gọi lại khi ứng dụng reactived (tức là chỉ chạy 1 lần đầu tiên duy nhất)
private void Application_Launching(object sender, LaunchingEventArgs e)
{
string msg = "Application_Launching";
}

//Sự kiện nay được triệu gọi khi ứng dụng được Activated (người sử dụng tương tác được)
// Lầu đầu khi ứng dụng chạy (Application_Launching) nó sẽ không được gọi, các lần sau nó sẽ tiếp tục
//được triệu gọi nếu như nó được activated (chuyển từ Suspended sang Foreground Lifetime)
private void Application_Activated(object sender, ActivatedEventArgs e)
{
string msg = "Application_Activated";
}

//Sự kiện sẽ được triệu gọi khi ứng dụng bị đưa vào trạng thái Suspend
//--> tức là khi nó che khuất ứng dụng, người sử dụng không thể tương tác
//Và nó sẽ không được triệu gọi khi sự kiện Closing sảy ra
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
string msg = "Application_Deactivated";
}

//Sự kiện được triệu gọi khi ứng dụng chuyển qua trạng thái đóng (terminate)
//và nó sẽ không thực thi khi ứng dụng vào trạng hái Deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
string msg = "Application_Closing";
}

—>Ta thường lưu thông tin cấp ứng dụng trong sự kiện Application_Deactivated và khởi tạo lại thông tin trong sự kiện Application_Activated.

- Cấp độ trang (xử lý trong mỗi trang .xaml.cs) – có 2 sự kiện chính:


//Sự kiện sảy ra khi trang được hiển thị Foreground
//Ta thường khởi tạo lại giá trị được lưu trữ trong hàm này
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
if(localsetting.Values["data"]!=null)
{
txtData.Text = localsetting.Values["data"].ToString();
}
}
//sự kiện sảy ra khi trang bị đóng hoặc bị trang khác đè lên
//Ta thường lưu thông tin cấp độ trang trong hàm nay
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
localsetting.Values["data"] = txtData.Text;
}

Bạn cần chú ý thứ tự diễn ra các sự kiện:

- Đầu tiên sự kiện ở cấp độ ứng dụng sẽ sảy ra trước

- Sau đó mới tới sự kiện ở cấp độ trang.

tức là Nếu trong 1 Project bạn vừa xử lý trạng thái ở cấp độ ứng dụng và cấp độ trang, khi  ứng dụng bị suspended thì tuần  tự sảy ra như sau:

hàm Application_Deactivated sảy ra trước sau đó mới tới OnNavigatedFrom.

- Tui có cung cấp lệnh lưu và phục hồi thông tin ở trên, các bạn có thể áp dụng vào ứng dụng của mình.

Để các bạn có thể dễ dàng thực hành bài tập này thì làm theo từng bước như sau:

 Bước 1:

Tạo một Project tên “LearnLifeCycle” như hình chụp dưới đây:

wp5_2Chú ý là chọn “Blank App (Windows Phone Silverlight)”, từ này các ví dụ Tui sẽ sử dụng loại Project này.

 Bước 2:

Tạo thêm 2 trang Page2.xamlPage3.xaml như hình dưới đây:

wp5_3Để tạo mới 1 trang thì bạn chỉ cần bấm chuột phải vào Project chọn/ Add/ New Item:

wp5_4Màn hình Add New Item sẽ hiển thị ra như dưới đây:

wp5_5

Chọn các thông số như hình, rồi bấm nút Add bạn sẽ có kết quả như mong muốn (tạo được 1 trang mới). Tương tự như vậy bạn có thể thêm Page3.xaml vào ứng dụng.

Bước 3:

Tiến hành XAML và coding cho Mainpage.xaml như sau:

wp5_6Xử lý coding cho Mainpage:


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 LearnLifeCycle.Resources;

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

// Sample code to localize the ApplicationBar
//BuildLocalizedApplicationBar();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
//Nếu còn về trước được
if (NavigationService.CanGoBack)
NavigationService.GoBack();//thì về trước
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
//xử lý chuyển qua trang mới
if(NavigationService.CanGoForward)
{
NavigationService.GoForward();
}
else
{
//tạo uri qua trang mới:
Uri newPage = new Uri("/Page2.xaml", UriKind.Relative);
//gọi lệnh chuyển trang
NavigationService.Navigate(newPage);
}
}
//Sự kiện sảy ra khi trang được hiển thị Foreground
//Ta thường khởi tạo lại giá trị được lưu trữ trong hàm này
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
if(localsetting.Values["data"]!=null)
{
txtData.Text = localsetting.Values["data"].ToString();
}
}
//sự kiện sảy ra khi trang bị đóng hoặc bị trang khác đè lên
//Ta thường lưu thông tin cấp độ trang trong hàm nay
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);

Windows.Storage.ApplicationDataContainer localsetting =
Windows.Storage.ApplicationData.Current.LocalSettings;
localsetting.Values["data"] = txtData.Text;
}
}
}

Tiếp tục ta thiết kế XAML cho Page2 và Page3 (2 trang này giống y xì nhau) chủ yếu dùng để test mà thôi:

Vì nó giống nhau nên phần XAML tui chỉ ví dụ 1 Page 2, Page 3 bạn tự copy + paste sang:


<phone:PhoneApplicationPage
x:Class="LearnLifeCycle.Page2"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel Grid.Row="0" Margin="12,17,0,28">
<TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock Text="page name 2" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="14,0,10,0">
<Button x:Name="btnPrevious" Content="Go to Previous Page" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Click="btnPrevious_Click"/>

</Grid>
<Button x:Name="btnNext" Content="Go to Next Page" HorizontalAlignment="Left" Margin="37,106,0,0" VerticalAlignment="Top" Click="btnNext_Click" Grid.Row="1"/>
</Grid>

</phone:PhoneApplicationPage>

Phần xử lý coding cho Page2.xaml.cs:


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;

namespace LearnLifeCycle
{
public partial class Page2 : PhoneApplicationPage
{
public Page2()
{
InitializeComponent();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
if (NavigationService.CanGoForward)
NavigationService.GoForward();
else
{
Uri newpage = new Uri("/Page3.xaml", UriKind.Relative);
NavigationService.Navigate(newpage);
}
}
}
}

Phần xử lý coding cho Page3.xaml.cs (giống page2):


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;

namespace LearnLifeCycle
{
public partial class Page3 : PhoneApplicationPage
{
public Page3()
{
InitializeComponent();
}

private void btnPrevious_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
}

private void btnNext_Click(object sender, RoutedEventArgs e)
{
if (NavigationService.CanGoForward)
NavigationService.GoForward();
else
{
Uri newpage = new Uri("/MainPage.xaml", UriKind.Relative);
NavigationService.Navigate(newpage);
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
}
}
}

Bây giờ Tui cần các bạn test các trường hợp sau:

1) Từ trang MainPage, nhập dữ liệu cho TextBox rồi bấm nút HOME

2) Sau đó nhấn nút Back

3) Từ MainPage nhập dữ liệu cho Textbox rồi chuyển qua trang 2

4) Từ trang 2 quay lại trang 1

5) Từ trang 2 qua trang 3

6) Từ trang 3 qua trang Mainpage.

Bài hướng dẫn kế tiếp tui sẽ trình bày về XAML và các control cơ bản trong Windows Phone 8.1,  các bạn chú ý theo dõi.

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

Bài 4: Đăng ký lập trình Windows Phone 8.1 trên thiết bị thật


Như ta đã biết Microsoft có hỗ trợ Emulator giúp chúng ta có thể lập trình thay thế thiết bị thật, tuy nhiên trong một số trường hợp thì ta không thể Test chính xác được trên thiết bị Emulator (ví dụ như Camera, Sensor…), vì vậy bài này Tui hướng dẫn các bạn cách đăng ký để có thể deploy phần mềm vào thiết bị thật để test một cách trực quan.

Bước 1:

- Cần chuẩn bị thiết bị thật + Dây cáp + cài đặt Driver hoàn chỉnh, thông thường khi mua điện thoại nhà cung cấp đã tích hợp sẵn do đó bạn chỉ cần cắm vào ngồi đợi 1 xí là máy sẽ cài đặt xong.

- Sau đó cắm thiết bị vào máy tính của bạn:

connect-htc-8x-to-pc

Bước 2:

Vào Start Screen bạn tìm kiếm Windows Phone Developer Registration 8.1 như hình Tui chụp ở dưới đây:

wp4_2

Bước 3:

Kích hoạt phần mềm:

wp4_3Bước 4:
Đăng ký

 

Bạn nhìn vòng tròn tròn đẹp đẹp Tui khoanh ở trên, nếu bạn chưa bao giờ đăng ký thì nó có nút Register và bạn bấm vào nút này để đăng ký, dĩ nhiên bạn cần có tài khoản Developer trước (nếu bạn  chưa biết thì vào link sau : http://clbtinhoc.dntu.edu.vn/index.php/huong-dan-dang-ky-tai-khoan-microsoft-developer-mien-phi-khong-can-visa/).

- Sau khi bấm Register: Bạn cần cung cấp đúng thông tin để đăng nhập

wp4_4Sau khi đăng ký thành công, bạn sẽ có màn hình sau (tới màn hình này là có thể sử dụng được thiết bị thật để lập trình).

wp4_5

Bạn cần chú ý là khi cắm thiết bị thật vào máy tính thì cần mở khóa màn hình, nếu không mở khóa thì bạn có thể gặp lỗi như sau:

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

Bài 3: Cách sử dụng Windows Phone Emulator 8.1


Trong bài này Tui sẽ hướng dẫn các bạn cách chạy Windows Phone Emulator cũng như cách sử dụng các công cụ và tính năng được tích hợp trong Emulator.

Windows Phone Emulator là gì? Bạn hiểu nôm na nó là một công cụ dùng để thay thế cho thiết bị thật để giúp lập trình viên có thể viết các ứng dụng và kiểm thử trên Emulator mà không cần đến thiết bị thật (Tức là nếu như ta không có tiền để mua một chú Dế thì cũng không sao, ta vẫn hoàn toàn lập trình được với Windows Phone). Tuy nhiên không phải tất cả các chức năng trong thiết bị thật đều có thể giả lập được trên Emulator, ví dụ như chức năng Camera (chỉ là các ô vuông chạy demo quanh màn hình).

Bạn có thể khởi động Windows Phone Emulator bằng các cách sau đây:

1) Khởi động từ Visual Studio

Từ Visual Studio ta chọn các Emulator cần chạy (ta có thể cập nhật thêm các Emulator bằng cách tải từ trang Microsoft cung cấp)

wp_3_3

2) Khởi động bằng command line (Không cần Visual Studio)

- Mở cửa sổ run bằng cách gõ tổ hợp phím Windows + R

- Rồi gõ lệnh sau:  “C:\Program Files (x86)\Microsoft XDE\8.1\XDE.exe” /vhd “C:\Pro
gram Files (x86)\Microsoft SDKs\Windows Phone\v8.1\Emulation\Images\Flash.vhd” /
video “720×1280″ /memsize 1024 /language 409 /creatediffdisk “%Temp%\dd.720×1280
.1024.vhd” /fastShutdown

Từ khóa “creatediffdisk” rất quan trọng, nếu ta thiếu nó thì Emulator vẫn chạy nhưng nó sẽ yêu cầu cấp quyền Admin, cái trớ trêu là nếu chạy với quyền Admin thì nó sẽ chỉnh sửa VHD image trong thư mục cài đặt, mà việc chỉnh sửa này rất nguy hiểm nó có thể không cho phép chúng ta khởi động Emulator từ Visual Studio nữa. Để biết thêm chi tiết thì bạn có thể gõ lệnh Run “XDE.exe /?“. Chú ý là nếu như bạn cài đặt với những chọn lựa mặc định của Microsoft thì bạn có thể copy + paste nguyên xi lệnh trên rồi gõ enter là hệ thống tự động kích hoạt Emulator.

wp_3_1Vì sao lại gõ đường dẫn như trên? bởi vì trong quá trình cài đặt hệ thống đã lưu trữ Emulator ở đây (do đó nếu bạn chỉ định đường dẫn khác trong quá trình cài đặt thì phải chọn đúng đường dẫn đó, còn để mặc định thì gõ như trên), ví dụ hình dưới đây là lưu trữ mặc định khi cài đặt:

wp_3_2

 

3) Sử dụng Windows Phone Power tool:

http://wptools.codeplex.com/

Cả 3 cách đều cho ra kết quả như sau:

wp_3_4 Chi tiết từng chức năng:

wp_3_5Windows Phone Emulator 8.1 có một điểm mới rất thú vị là hỗ trợ Chạm Đa Điểm giúp ta có thể lập trình đa điểm tốt  thay thế cho thiết bị thật: Khi bạn bấm vào biểu tượng Ngón Trỏ Tay thì màn hình sẽ xuất hiện 3 hình tròn cho phép chúng ta: Phóng to, thu nhỏ, xoay, quay, di chuyển, bẻ góc….

wp_3_15Windows Phone 8.1 hỗ trợ SD Card, nó được để trong Công Cụ Sử dụng Windows Phone Emulator nâng cao, bây giờ bạn bấm vào nút này để tiếp tục xem các chức năng nâng cao của Emulator (Nút cuối cùng):

wp_3_6Tab Accelerometer: Giả lập cảm biến gia tốc, bạn có thể đổi các hướng X,Y,Z tùy ý để test gia tốc bằng cách di chuyển nút hình tròn màu nghệ:

wp_3_7Hoặc bạn cũng có thể chọn những hướng chuẩn thường sử dụng bằng cách chọn mục Combobox Orientation:

wp_3_8Để chụp hình Emulator mà bạn đang thao tác, bạn vào Tab Screenshot:

wp_3_9Để cấu hình SD Card bạn vào tab SD Card:

wp_3_10Local folder: Chỉ định nơi lưu trữ

Bấm Insert SD Card để tạo SD Card hệ thống sẽ tiến hành đồng bộ, nút Insert SD Card sẽ được đổi thành “Eject SD Card”, đồng thời trong Windows Phone Emulator cũng hiển thị Message Box xác nhận:

wp_3_12Windows Phone Emulator:

wp_3_11Chọn Yes để chấp nhận và di chuyển tới màn hình Storage Sense:

wp_3_13Đồng thời bạn quan sát thư mục SD Card trong PC cũng đổi như sau:

wp_3_14Các tab khác ta sẽ đề cập tới sau khi làm các bài tập có liên quan.

Ngoài các chức năng trên ta cần biết thêm các phím tắt để thao tác vơi Windows Phone Emulator:

– Sử dung Keyboard cho Emulator:

+ Nhấn Phím Page Up/Down để cho phép tắt mở chức năng nhập thông tin từ bàn phím cho Emulator –> Tăng tốc độ.

Dưới đây là bảng chi tiết mà Microsoft cung cấp:

Computer hardware key hardware button Notes
F1 BACK Long presses work as expected.
F2 START Long presses work as expected.
F3 SEARCH
F4 Not applicable.
F5 Not applicable.
F6 CAMERA HALF A dedicated camera button that is pressed halfway.
F7 CAMERA FULL A dedicated camera button.
F8 Not applicable.
F9 VOLUME UP
F10 VOLUME DOWN
F11 Not applicable.
F12 POWER Press the F12 key twice to enable the lock screen.Long presses work as expected.
ESC BACK Long presses work as expected.
PAUSE/BREAK Toggle Keyboard Toggles the hardware keyboard.
PAGE UP Keyboard Up Enables the hardware keyboard.
PAGE DOWN Keyboard Down Disables the hardware keyboard.

Link : http://msdn.microsoft.com/en-us/library/windowsphone/develop/dn632391.aspx

Như vậy Tui đã giới thiệu sơ lược một số chức năng trong Windows Phone Emulator, hi vọng nó sẽ giúp ích được cho bạn trong quá trình lập trình. Khi gặp các bài tập có liên quan Tui sẽ bổ sung tiếp để các bạn dễ nắm bắt.

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

 

 

 

Bài 2: Cách tạo một Project Windows Phone 8.1


Ở bài 1 các bạn đã chuẩn bị đầy đủ vũ khí đạn dược cho việc chiến đấu với Windows Phone 8.1, trong bài này Tui sẽ hướng dẫn các bạn cách tạo một Project Windows Phone 8.1 như thế nào, đặc biệt phải hiểu được cấu trúc, thành phần, cách đóng gói và triển khai ứng dụng lên Emulator cũng như thiết bị thật như thế nào.

Bước 1:

- Khởi động Visual Studio Ultimate 2013, vào menu File/ chọn New/ Project (hoặc nhấn tổ hợp phím Ctrl + Shift+N) như hình dưới đây:

wp_bai2_1Bước 2:

Ở màn hình New Project ta chọn các thông số như hình dưới đây:

wp_2_1- Phần Template bên tay trái ta chọn Windows Phone Apps

- Phần danh sách loại Project ở giữa màn hình ta chọn Blank App (Windows Phone)

- Mục Name: Đặt tên cho Project, ở đây ta đặt FirstAppSample

–> Sau đó bấm nút OK để tạo một Windows Phone Project

Sau đây là cấu trúc của một Project Windows Phone:

wp_2_2Hệ thống sẽ tự động tạo ra các tập tin: App.xaml, MainPage.xaml, Package.appxmanifest…

- Toàn bộ cấu hình của ứng dụng đều nằm trong Package.appxmanifest.

- MainPage.xaml sẽ được tải đầu tiên khi ứng dụng được chạy (mặc lấy làm màn hình chính), ta cũng có thể thay thể bởi các màn hình khác.

- Assets: Chứa tập hợp các tập tin logo, icon… ta có thể kéo thả các tập tin vào đây: Hình ảnh, âm thanh…

Bây giờ ta thử kéo thả 1 Button vào MainPage :

–> Double click vào MainPage.xaml để hiển thị chi tiết các vùng trong môi trường làm việc Visual Studio:

wp_2_3Ở trên Tui đánh dấu từ 1–>5:

 Vùng số 1: Hiển thị các control để kéo thả vào vùng số 2, nếu như Vùng số 1 không xuất hiện thì bạn vào Menu View/ Toolbox (hoặc nhấn tổ hợp phím Ctrl +Alt+ X)

Vùng số 2: Nơi hiển thị Giao diện Điện Thoại cho phép ta thiết kế ứng dụng

Vùng số 3: Nơi cho phép ta dùng XAML code để thiết kế giao diện, chú ý rằng ở Vùng số 1 mỗi lần ta kéo thả control vào vùng số 2 thì vùng số 3 tự động cập nhật các XAML code (tự phát sinh). Có nghĩa là ta có thể thiết kế giao diện cho vùng Số 2 bằng cách kéo thả ở vùng số 1 vào hoặc gõ bằng XAML code trong vùng số 3.

Vùng số 4: Cấu trúc thư mục của ứng dụng

Vùng số 5: Cấu hình Properties, Event… cho các đối tượng trong ứng dụng. Ví dụ khi kéo Button ra tui đặt tên cho Button này là btnClickMe, thì trong mục Properties có ô Name ta gõ vào btnClickMe. Nội dung hiển thị cho Button này là “Click Me!” thì ta gõ vào ô Content.

Để gán sự kiện cho Button ta Double click vào Button đó thì nó tự động phát sinh sự kiện hoặc ta vào tab Event để thiết lập sự kiện cho control:

wp_2_5Ta xem sự kiện phát sinh, ở đây khi chạm vào Button ta sẽ đổi thành màu Vàng:

wp_2_4Bạn quan sát là đối với một màn hình thì hệ thống sẽ có tập tin: .xaml và .xaml.cs . Ví dụ MainPage.xaml là tập tin để thiết kế giao diện, MainPage.xaml.cs là nơi để coding chúng được tách biệt ra làm 2 tập tin độc lập nhưng cùng làm việc cho lớp MainPage.

Bây giờ ta có thể nhấn phím F5 để chạy ứng dụng, chú ý rằng mặc định sẽ chạy trên Emulator, ta có thể lựa chọn chạy trên thiết bị thật cũng như chọn các loại Emulator khác nhau bằng cách chọn theo mục như hình dưới đây:

wp_2_6Để chạy trên máy thật ta chọn Device

Để chạy máy ảo Emulator thì tùy ta chọn mục Emulator, ứng với mỗi loại khác nhau thì Emulator hiển thị khác nhau.

Kết quả sau khi ta thực hiện chương trình trên:

wp_2_7Khác so với Windows Phone 8.0 (.xap), Windows Phone 8.1 biên dịch ra tập tin .exe wp_2_8Cách sử dụng Package.appxmanifest trong Project:

Tập tin này cho phép ta cấu hình các đặc tính của ứng dụng: Camera, Sensor, Contact, Music Library…

Ta double click vào tập tin này nó sẽ hiển thị ra với nhiều Tab: Capabilities, Application, Declarations, Content URIs, Visual Assets, Packaging, Requirements. Mỗi tab có những chức năng cấu hình khác nhau (ta cần hiểu rõ để cấu hình ứng dụng cho tốt):

wp_2_9Tab Application: Dùng để thiết lập các thuộc tính và mô tả cho ứng dụng

Tab Visual Assets: Dùng để cấu hình hỗ trợ các độ phân giải khác nhau, cùng các thiết lập Logo, Splash Screen….

Tab Requirements:  Tab này cho phép ta yêu cầu cấu hình phần cứng của thiết bị khi cài đặt ứng dụng, ví dụ như yêu cầu phần cứng phải có Sensor, NFC, Camera… nếu không có thì không cho phép cài ứng dụng.

Tab Capabilities: Thiết lập các đặc tính cho phép ứng dụng có thể sử dụng các tính năng trong thiết bị, ví dụ như: Cho phép sử dụng Contacts, Microphone, SD Card, Webcam….

Tab Packaging: Thiết lập thông số cấu hình phiên bản, package name và display name…

Tab Declarations: Để thiết lập các khai báo cũng như thuộc tính cho chúng

Tab Content URIs: Dùng để khai báo các HTTPS URI để sử dụng window.external.notify để gửi sự kiện ScriptNotify tới ứng dụng.

Chú ý:  Để thiết lập trang mặc định khi ứng dụng được khởi động thì ta sửa hàm sau trong lớp App.xaml.cs:


protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
          ...
                if (!rootFrame.Navigate(typeof(MainPage), e.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
         ...
        }

Thành:


protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
          ...
                if (!rootFrame.Navigate(typeof(SecondPage), e.Arguments))
                {
                    throw new Exception("Failed to create initial page");
                }
         ...
        }

Muốn chạy trang nào mặc định thì ta sửa như trên, ở bên trên Tui ghi là Secondpage, bạn có thể chỉ định bất kỳ trang nào vào đây.

Bài kế tiếp Tui sẽ hướng dẫn các bạn cách sử dụng Windows Phone 8.1 Emulator, việc sử dụng Emulator thành thạo là rất quan trọng nó giúp lập trình viên tăng tốc độ xử lý coding đặc biệt nó dường như có thể thay thế cho thiết bị thật.

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

Follow

Get every new post delivered to your Inbox.

Join 796 other followers

%d bloggers like this: