【轉】http://www.cnblogs.com/yuzukwok/p/3884377.html

來自:http://www.cnblogs.com/yuzukwok/p/3884377.html

An Introduction to Xamarin.Forms

來源:http://developer.xamarin.com/guides/cross-platform/xamarin-forms/introduction-to-xamarin-forms/

概覽css

Xamarin.Forms 是一個幫助開發者快速建立跨平臺UI的框架。它爲ios,Android,Windows Phone上的原生控件的使用提供了一層抽象.這意味着應用程序之間能夠共享大部分UI代碼,同時還能保持相應平臺的界面外觀樣式。html

Xamarin.Forms使用C#編寫,可以適應於快速開發愈來愈複雜的應用程序。由於採用 Xamarin.Form的應用程序是原生應用程序,沒必要受制於其餘相似開發工具包的限制,如瀏覽器沙箱, 有限的API,糟糕的性能. 使用 Xamarin.Forms編寫的程序可以使用下層平臺的任何API或者特性,包括但不限於CoreMotion, PassKit, and StoreKit 之於iOS; NFC 和Google Play Services 之於 Android;  Tiles 之於 Windows Phone.這也意味着你能夠開發一個應用程序部分使用 Xamarin.Forms建立的UI,部分使用原生 UI 開發包來編寫.node

Xamarin.Forms 應用程序和傳統的跨平臺應用的架構是同樣的。. 最多見的辦法是使用 Portable Libraries 或者 Shared Projects 來共享代碼, 而後建立平臺相關的項目來消費使用共享代碼.android

Xamarin.Forms使用兩種方式建立用戶界面。第一種是用Xamarin Forms提供的API直接在源代碼裏建立UI,另外一種可選的方法是使用 Extensible Application Markup Language (XAML),(一種MS用於定義界面的標記語言). 用戶界面將使用XAML定義在一個XML文件中,運行時的行爲則被定義在單獨的代碼文件中。瞭解更多關於XAML,能夠閱讀 XAML Overview 文檔 What is XAML.ios

本指南只是Xamarin Forms框架基礎,包含如下主題windows

  • 安裝Xamarin.Forms.
  • 在 Visual Studio 或Xamarin Studio中新建解決方案.
  • 如何使用Xamarin.Forms中的頁面和控件
  • 如何在頁面間導航
  • 如何設置數據綁定

要求

Xamarin.Forms 應用程序能夠運行在以下移動操做系統中:瀏覽器

  • Android 4.0 或以上
  • iOS 6.1 或以上
  • Windows Phone 8 (使用Visual Studio)

Xamarin.Forms 爲了部分控件(如DatePicker)須要要求安裝 Windows Phone Toolkit .架構

咱們假定開發者已經熟悉 Portable Class Libraries 和Shared Projects用法app

Mac 系統要求

在OSX上開發Xamarin.Forms程序須要安裝Xamarin Studio 5 . 開發iOS程序則要求安裝 Xcode 5  (操做系統要求 OS X 10.8 或以上). Windows Phone 程序無法在OSX上開發; IDE也無法建立包含Window Phone的項目模板.框架

Windows 系統要求

Xamarin.Forms 應用程序可使用Visual Studio 2012(或更新的版本)開發.

  • PCL 解決方案模板須要.NET 4.5上的Profile 78 ( Visual Studio 2012 能夠安裝Net4.5, Visual Studio 2013已內置). 同時須要安裝Windows Phone SDK ,不然會發生 Project type not supported 的錯誤.
  • Shared Project 項目模板須要安裝 Visual Studio 2013 Update 2.

開始使用Xamarin Forms

在開始下面的討論前, 咱們須要瞭解,Xamarin.Forms 實際上是以 .NET Portable Class Library (PCL可移植類庫)的形式實現,由於這樣能夠在多平臺很方便的共享API. 建立應用程序的第一步就是建立解決方案文件

一個Xamarin.Forms 解決方案一般有如下項目組成:

  • Portable Library - 這個項目是包含全部共享UI和其餘共享的代碼用於跨平臺應用程序的類庫.
  • Xamarin.Android Application - 這個項目包含Android相關的代碼和一個Android版應用程序的入口點函數.
  • Xamarin.iOS Application - 這個項目包含iOS相關的代碼和一個IOS版應用程序的入口點函數.
  • Windows Phone Application - 這個項目包含Windows Phone相關的代碼和一個Windows Phone版應用程序的入口點函數.

Xamarin 3.0 提供的解決方案模板,能夠建立一個Xamarin Forms程序所必須的全部項目。

在 Xamarin Studio 中, 選File > New > Solution. 在新建解決方案對話框中選C# > Mobile Apps, 而後選擇 Blank App (Xamarin.Forms Portable) .下面是該操做的截圖:

輸入項目名,並按OK按鈕就能夠了. 模板會建立一個包含三個項目的解決方案. 

使用Xamarin Studio 建立的解決方案不包含 Windows Phone 項目. 使用Visual Studio 新建 Xamarin.Forms 解決方案的話則支持 iOS, Android和 Windows Phone. 須要注意的是雖然 Xamarin Studio不支持建立Windows Phone 應用程序,可是他仍是可以打開一個包含Windows Phone 應用程序項目的解決方案 (如一個被Visual Studio建立的解決方案). 你能夠查看 Windows Phone 代碼,可是無法編譯和部署在Xamarin Studio.

查看一個 Xamarin.Forms 應用程序

默認的模板建立一個最簡單 Xamarin.Forms 應用程序. 若是你運行它,你會看到以下界面:

在上面的截圖中,每一個界面都是使用Xamarin Forms的Page 的效果. 一個Xamarin.Forms.Page在Android中 就是Activity對象 ,在iOS中就是 View Controller對象, 在Windows Phone就是 Page 對象. 上面截圖的HelloXamarinFormsWorld 例子是使用一個Xamarin.Forms.ContentPage 對象,而後展現一個標籤.

爲了最大化重用啓動代碼, Xamarin.Forms 應用程序會建立一個叫App的簡單類,做用是實例化第一個展現的Page對象.下面的代碼就是一個App類的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class App {  public static Page GetMainPage()  {  return new ContentPage  {  Content = new Label  {  Text = "Hello, Forms !",  VerticalOptions = LayoutOptions.CenterAndExpand,  HorizontalOptions = LayoutOptions.CenterAndExpand,  },  };  } }

上述代碼實例化一個ContentPage 對象,該對象會顯示一個單行的 Label,並設置了在頁面中水平和垂直居中.

在各平臺啓動初始化 Xamarin.Forms Page

爲了在應用程序中使用Xamarin Forms Page對象, 每一個平臺上的項目必須初始化 Xamarin.Forms 框架並在啓動時提供一個實例化的ContentPage的對象. 不一樣平臺上的啓動代碼是不同的。

Android

在Android中啓動初始化 Xamarin.Forms 頁面, 你必須建立一個使用MainLauncher特性的Activity,就像以前的傳統的Android應用同樣; 除此之外你的activity 還必須繼承至Xamarin.Forms.Platform.Android.AndroidActivity,而後重寫OnCreate方法,在其中進行 Xamarin.Forms framework的初始化,顯示初始的Page等工做。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace HelloXamarinFormsWorld.Android {  [Activity(Label = "HelloXamarinFormsWorld", MainLauncher = true)]  public class MainActivity : AndroidActivity  {  protected override void OnCreate(Bundle bundle)  {  base.OnCreate(bundle);   Xamarin.Forms.Forms.Init(this, bundle);   SetPage(App.GetMainPage());  }  } }

上述代碼會建立一個 Xamarin.Android 應用程序

iOS

在一個 Xamarin.iOS 應用程序中,須要在 AppDelegate 類中初始化 Xamarin.Forms 框架,而後設置RootViewController爲初始的Xamarin.Forms Page. 以下面代碼顯示的,這些都要在 FinishedLaunching 方法中完成 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Register("AppDelegate")] public partial class AppDelegate : UIApplicationDelegate {  UIWindow window;   public override bool FinishedLaunching(UIApplication app, NSDictionary options)  {  Forms.Init();   window = new UIWindow(UIScreen.MainScreen.Bounds);   window.RootViewController = App.GetMainPage().CreateViewController();   window.MakeKeyAndVisible();   return true;  } }

和andoroid同樣,  FinishedLaunching事件的第一步是經過Xamarin.Forms.Forms.Init()初始化 Xamarin.Forms 框架。這樣作緣由是由於Xamarin.Forms須要在應用程序中全局加載. 下一步是設置應用程序的根view controller對象. 這須要調用在跨平臺類庫中建立的HelloWordPage對象的 CreateViewController()方法。

Windows Phone

在一個 Windows Phone項目中初始頁會初始化Xamarin.Forms框架,而後用 Xamarin.Forms Page對象設置起始頁內容. 下面代碼是如何操做的一個例子:

1
2
3
4
5
6
7
8
9
10
public partial class MainPage : PhoneApplicationPage {  public MainPage()  {  InitializeComponent();   Forms.Init();  Content = HelloXamarinFormsWorld.App.GetMainPage().ConvertPageToUIElement(this);  } }

既然咱們已經開始對 Xamarin.Forms有些瞭解,而後咱們開始更詳細討論Xamarin Forms.

Views and Layouts

Xamarin.Forms使用了一個很簡單的API,經過Control對象和Layouts對象組合用於建立UI界面。 在運行時, Xamarin.Forms control會映射到相應的原生控件,並用原生控件來呈現.用於 Xamarin.Forms 應用的界面展現主要是以下4個類:

  • View - 在其餘平臺一般會被稱爲controls 或 widgets. 就是至關於標籤,按鈕,文本框等等UI元素.
  • Page - 一個Page在應用程序程序表明一個屏幕的內容. 他相似於Android的 Activity, Windows Phone 的Page,  iOS 的View Controller.
  • Layout - 一種View的子類. 做爲放置界面顯示的View對象和其餘Layout的容器. Layout 一般包含如何組織呈現子view的邏輯.
  • Cell - 這個類是專門的元素用於表明list或table中的項目,它描述了列表中每一個元素是如何展現的.

下面是經常使用的Control:

Xamarin.Forms Control Description
Label 只讀顯示文本
Entry 單行輸入文本框
Button 按鈕
Image 用於展現圖片的控件
ListView 列表清單. 

Controls 自己是由 layout進行佈局控制的. Xamarin.Forms 有兩類不一樣的佈局控制方式:

  • Managed Layouts -  layout負責內部的控件的位置和大小,而且遵循 CSS box model. 應用程序不會直接嘗試去設置控件的大小和位置. 內置的一個Managed Layout的是 theStackLayout.
  • Unmanaged Layouts -和managed layouts相反, unmanaged layouts 不會自動調整屏幕中控件的位置. 一般用戶在加入到layout時要本身指定好位置和大小。內置的 AbsoluteLayout 是一個 unmanaged layout .

讓咱們具體討論下 StackLayout 和AbsoluteLayout .

StackLayout

StackLayout 是最多見的managed layout. StackLayout 能夠知足那些跨平臺應用程序開發中但願無視屏幕尺寸,系統自動調整控件位置的需求。每一個子元素按照加入layout的順序依次被定位,不管橫向仍是豎向 . StackLayout會使用多少空間,取決於HorizontalOptions 和LayoutOptions 屬性的設置, 默認StackLayout 會使用整個屏幕區域

下列代碼是使用 StackLayout 排列3個Label 控件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public class StackLayoutExample: ContentPage {  public StackLayoutExample()  {  Padding = new Thickness(20);  var red = new Label  {  Text = "Stop",  BackgroundColor = Color.Red,  Font = Font.SystemFontOfSize (20)  };  var yellow = new Label  {  Text = "Slow down",  BackgroundColor = Color.Yellow,  Font = Font.SystemFontOfSize (20)  };  var green = new Label  {  Text = "Go",  BackgroundColor = Color.Green,  Font = Font.SystemFontOfSize (20)  };   Content = new StackLayout  {  Spacing = 10,  Children = { red, yellow, green }  };  } }

下列代碼是使用XAML進行一樣的佈局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  x:Class="HelloXamarinFormsWorldXaml.StackLayoutExample1"  Padding="20">   <StackLayout Spacing="10">   <Label Text="Stop"  BackgroundColor="Red"  Font="20" />   <Label Text="Slow down"  BackgroundColor="Yellow"  Font="20" />   <Label Text="Go"  BackgroundColor="Green"  Font="20" />   </StackLayout> </ContentPage>

下面的截圖咱們能夠看到默認 StackLayout 會垂直排列

能夠經過下面的代碼對 Orientation 和Vertical屬性進行設置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class StackLayoutExample: ContentPage {  public StackLayoutExample()  {  // 爲看得更清楚建立label的代碼已被移除   Content = new StackLayout  {  Spacing = 10,  VerticalOptions = LayoutOptions.End,  Orientation = StackOrientation.Horizontal,  HorizontalOptions = LayoutOptions.Start,  Children = { red, yellow, green }  };  } }

下列代碼是使用XAML進行一樣的佈局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  x:Class="HelloXamarinFormsWorldXaml.StackLayoutExample2"  Padding="20">   <StackLayout Spacing="10"  VerticalOptions="End"  Orientation="Horizontal"  HorizontalOptions="Start">   <Label Text="Stop"  BackgroundColor="Red"  Font="20" />   <Label Text="Slow down"  BackgroundColor="Yellow"  Font="20" />   <Label Text="Go"  BackgroundColor="Green"  Font="20" />   </StackLayout> </ContentPage>

修改後代碼的運行截圖以下

儘管不能顯式地設置StackLayout內控件的大小, 可是能夠經過HeightRequest 和WidthRequest 屬性告訴layout引擎控件具體的大小. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var red = new Label {  Text = "Stop",  BackgroundColor = Color.Red,  Font = Font.SystemFontOfSize (20),  WidthRequest = 100 }; var yellow = new Label {  Text = "Slow down",  BackgroundColor = Color.Yellow,  Font = Font.SystemFontOfSize (20),  WidthRequest = 100 }; var green = new Label {  Text = "Go",  BackgroundColor = Color.Green,  Font = Font.SystemFontOfSize (20),  WidthRequest = 200 };  Content = new StackLayout {  Spacing = 10,  VerticalOptions = LayoutOptions.End,  Orientation = StackOrientation.Horizontal,  HorizontalOptions = LayoutOptions.Start,  Children = { red, yellow, green } };

下列代碼是使用XAML進行一樣的佈局:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  x:Class="HelloXamarinFormsWorldXaml.StackLayoutExample3"  Padding="20">   <StackLayout Spacing="10"  VerticalOptions="End"  Orientation="Horizontal"  HorizontalOptions="Start">   <Label Text="Stop"  BackgroundColor="Red"  Font="20"  WidthRequest="100" />   <Label Text="Slow down"  BackgroundColor="Yellow"  Font="20"  WidthRequest="100" />   <Label Text="Go"  BackgroundColor="Green"  Font="20"  WidthRequest="200" />   </StackLayout> </ContentPage>

修改後的程序運行結果:

Absolute Layout

AbsoluteLayout屬於 unmanaged layout. 在layout內的控件必須顯式設置好本身的位置. 這個概念和老早的windows forms和ios平臺(沒有使用constarints)上控件定位的方法很像. 因爲設置了具體精確的定位位置,咱們須要在不一樣尺寸的屏幕上對layout進行測試來保證效果。

下面是使用 AbsoluteLayout的簡單例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public class MyAbsoluteLayoutPage : ContentPage {  public MyAbsoluteLayoutPage()  {  var red = new Label  {  Text = "Stop",  BackgroundColor = Color.Red,  Font = Font.SystemFontOfSize (20),  WidthRequest = 200,  HeightRequest = 30  };  var yellow = new Label  {  Text = "Slow down",  BackgroundColor = Color.Yellow,  Font = Font.SystemFontOfSize (20),  WidthRequest = 160,  HeightRequest = 160  };  var green = new Label  {  Text = "Go",  BackgroundColor = Color.Green,  Font = Font.SystemFontOfSize (20),  WidthRequest = 50,  HeightRequest = 50   };  var absLayout = new AbsoluteLayout();  absLayout.Children.Add(red, new Point(20,20));  absLayout.Children.Add(yellow, new Point(40,60));  absLayout.Children.Add(green, new Point(80,180));   Content = absLayout;  } }

Conceptually 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  x:Class="HelloXamarinFormsWorldXaml.AbsoluteLayoutExample"  Padding="20">   <AbsoluteLayout>   <Label Text="Stop"  BackgroundColor="Red"  Font="20"  AbsoluteLayout.LayoutBounds="20,20,200,30" />   <Label Text="Slow down"  BackgroundColor="Yellow"  Font="20"  AbsoluteLayout.LayoutBounds="40,60,160,160" />   <Label Text="Go"  BackgroundColor="Green"  Font="20"  AbsoluteLayout.LayoutBounds="80,180,50,50" />   </AbsoluteLayout>  </ContentPage>

下面的截圖就是最後呈現的結果

須要注意每一個被加入Children集合對象的順序影響了 屏幕上元素的Z-order – 第一個加入的在最底下 而隨後加入的控件在他的上面, 會產生覆蓋 (像例子中的綠色標籤).因此絕對佈局控件時要注意當心覆蓋致使隱藏其餘控件 

  Xamarin.Forms中的列表

ListViews在移動應用程序是一個常見控件,因此咱們能夠詳細討論下. ListView 用於展現一個集合中的項目。在ListVIew中每一個項目都是由一個cell組成.默認ListView會使用內置的 TextCell 來輸出一個單行文本。下面的代碼是使用ListView的簡單例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var listView = new ListView {  RowHeight = 40 }; listView.ItemsSource = new string []  {  "Buy pears",  "Buy oranges",  "Buy mangos",  "Buy apples",  "Buy bananas"  }; Content = new StackLayout {  VerticalOptions = LayoutOptions.FillAndExpand,  Children = { listView } };

下面是運行的截圖

和一個自定義類綁定

自定義的類也可使用ListView來綁定顯示. 咱們定義如下類:

1
2
3
4
 public class TodoItem {  public string Name { get; set; }  public bool Done { get; set; } }

 ListView 能夠像下面這樣使用:

1
2
3
4
5
6
7
listView.ItemSource = new TodoItem [] {  new TodoItem {Name = "Buy pears"},  new TodoItem {Name = "Buy oranges", Done=true},  new TodoItem {Name = "Buy mangos"},  new TodoItem {Name = "Buy apples", Done=true},  new TodoItem {Name = "Buy bananas", Done=true} };

爲了控制在列表中顯示的內容,須要建立一個binging,並設置綁定的屬性 - 在這個例子中是 Name 屬性.

1
2
listview.ItemTemplate = new DataTemplate(typeof(TextCell)); listview.ItemTemplate.SetBinding(TextCell.TextProperty, "Name");

 

在ListView中選擇一個項目

在ListView中實現ItemSelected 事件能夠響應界面上的點擊事件,下面代碼展現顯示一個簡單提示框:

1
2
3
listView.ItemSelected += (sender, e) => {  DisplayAlert("Tapped!", e.Item + " was tapped.", "OK", null); };

在一個 NavigationPage中的話,可使用 Navigation.PushAsync 方法打開一個新的Page進行導航. ItemSelected 事件中能夠經過 e.SelectedItem訪問選中的綁定對象, 咱們能夠繼續把對象綁定到新的Page而後經過 PushAsync方法展現:

1
2
3
4
5
listView.ItemSelected += (sender, e) => {  var todoItem = (TodoItem)e.SelectedItem;  var todoPage = new TodoItemPage(todoItem); // so the new page shows correct data  Navigation.PushAsync(todoPage); };

每一個平臺的導航方式不同的.更多內容在 Navigation.

自定義一個Cell的樣式

咱們能夠經過建立一個ViewCell的子類,並設置到ListView的ItemTemplate屬性上來實現Cell樣式的自定義

看一下下面的截圖樣式

這個cell由一個 Image 控件和兩個Label控件組成. 爲了建立這個自定義的佈局,咱們須要建立一個 ViewCell的子類:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class EmployeeCell : ViewCell {  public EmployeeCell()  {  var image = new Image  {  HorizontalOptions = LayoutOptions.Start  };  image.SetBinding(Image.SourceProperty, new Binding("ImageUri"));  image.WidthRequest = image.HeightRequest = 40;   var nameLayout = CreateNameLayout();   var viewLayout = new StackLayout()  {  Orientation = StackOrientation.Horizontal,  Children = { image, nameLayout }  };  View = viewLayout;  }   static StackLayout CreateNameLayout()  {   var nameLabel = new Label  {  HorizontalOptions= LayoutOptions.FillAndExpand  };  nameLabel.SetBinding(Label.TextProperty, "DisplayName");   var twitterLabel = new Label  {  HorizontalOptions = LayoutOptions.FillAndExpand,  Font = Fonts.Twitter  };  twitterLabel.SetBinding(Label.TextProperty, "Twitter");   var nameLayout = new StackLayout()  {  HorizontalOptions = LayoutOptions.StartAndExpand,  Orientation = StackOrientation.Vertical,  Children = { nameLabel, twitterLabel }  };  return nameLayout;  } }

代碼中的內容不少

  • 它加入一個 Image控件,而後綁定ImageUri屬性到 Employee 對象. 
  • 它建立了 StackLayout包含垂直排列的兩個標籤. 標籤綁定Employee 對象的DisplayName 屬性和 Twitter 屬性.
  • 它建立另外一個 StackLayout 用於放置Image 和第二步建立的 StackLayout . 而後使用水平排列.

一旦自定義的 cell類建立好,咱們可使用在ListView中 DataTemplate對象:

1
2
3
4
5
6
7
List<Employee> myListOfEmployeeObjects = GetAListOfAllEmployees(); var listView = new ListView {  RowHeight = 40 }; listView.ItemsSource = myListOfEmployeeObjects; listView.ItemTemplate = new DataTemplate(typeof(EmployeeCell));

向 ListView傳入一個Empolyee集合對象,每一個cell都會使用EmployeeCell類來呈現ListView 會把 Employee 對象經過BindingContext傳入EmployeeCell 

使用XAML來自定義一個列表

以前的代碼能夠經過以下XAML實現

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  xmlns:local="clr-namespace:XamarinFormsXamlSample;assembly=XamarinFormsXamlSample"  xmlns:constants="clr-namespace:XamarinFormsSample;assembly=XamarinFormsXamlSample"  x:Class="XamarinFormsXamlSample.Views.EmployeeListPage"  Title="Employee List">   <ListView x:Name="listView"  IsVisible="false"  ItemsSource="{x:Static local:App.Employees}"  ItemSelected="EmployeeListOnItemSelected">  <ListView.ItemTemplate>  <DataTemplate>  <ViewCell>  <ViewCell.View>  <StackLayout Orientation="Horizontal">   <Image Source="{Binding ImageUri}"  WidthRequest="40"  HeightRequest="40" />   <StackLayout Orientation="Vertical"  HorizontalOptions="StartAndExpand">   <Label Text="{Binding DisplayName}"  HorizontalOptions="FillAndExpand" />   <Label Text="{Binding Twitter}"  Font="{x:Static constants:Fonts.Twitter}"/>   </StackLayout>  </StackLayout>  </ViewCell.View>  </ViewCell>  </DataTemplate>  </ListView.ItemTemplate>  </ListView> </ContentPage>

 

數據綁定

 Xamarin.Forms 應用程序使用數據綁定很是方便地顯示和交互數據.它在用戶界面和底層應用程序創建之間的鏈接. 當用戶編輯文本框的內容時,數據綁定自動更新了所關聯底層對象的屬性 。 BindableObject 包含了不少內容用於實現數據綁定

數據綁定定義了兩個對象間的關係. source 對象提供數據.  target對象消費使用來自source數據 (一般是顯示). 例如,一個Label會顯示Employee 對象.Employee 對象就是 source, Label 就是 target.

如何在 Xamarin.Forms 對象(如 Page 和 Control) 中使用數據綁定,須要遵循下面兩步:

  • 設置要綁定對象的 BindingContext 屬性 ,用於綁定的源對象通常都要實現 INotifyPropertyChanged 接口.
  •  Xamarin.Forms 的對象要調用SetBinding 方法進行綁定.

 SetBinding 方法有兩個參數. 第一個參數是綁定的類型信息. 第二個參數須要提供綁定什麼內容和如何綁定的信息. 通常狀況下能夠設置爲BindingContext中文本型的屬性名, 若是咱們直接要綁定, 咱們能夠這樣寫

1
someLabel.SetBinding(Label.TextProperty, new Binding("."));

點號告訴Xamarin.Forms直接使用 BindingContext做爲數據源,而不是 BindingContext的某個屬性. 通常在BindingContext是一個簡單類型,如string或integer.

爲了幫助理解如何綁定一個對象到Page上,能夠看看下面的截圖

這個 Page使用瞭如下控件:

  • Xamarin.Forms.Image
  • Xamarin.Forms.Label
  • Xamarin.Forms.Entry
  • Xamarin.Forms.Button

Page對象經過構造子傳入Employee對象. 

1
2
3
4
5
6
7
8
9
10
11
12
public EmployeeDetailPage(Employee employeeToDisplay) {  this.BindingContext = employeeToDisplay;   var firstName = new Entry()  {  HorizontalOptions = LayoutOptions.FillAndExpand  };  firstName.SetBinding(Entry.TextProperty, "FirstName");   // Rest of the code omitted… }

代碼第一行設置了 BindingContext爲 一個.NET 對象 –這告訴底層界面須要綁定對象是誰. 下一行實例化了 Xamarin.Forms.Entry 控件. 最後一行綁定 Xamarin.Forms.Entry 和用於顯示的employee對象;  Entry控件Text 屬性被綁定到BindingContext對象的 FirstName 屬性.Entry控件的變化會自動更新到employeeToDisplay 對象. 一樣, 若是 employeeToDisplay.FirstName的變化也會引發 Entry 控件的顯示.綁定是雙向的.

爲了讓雙向綁定起做用, 模型類必須實現 INotifyPropertyChanged接口.

INotifyPropertyChanged

INotifyPropertyChanged 接口用於當一個對象值發生變化時須要經過客戶端的場景,接口很簡單:

1
2
3
4
5
public interface INotifyPropertyChanged {  event PropertyChangedEventHandler PropertyChanged; } 

INotifyPropertyChanged的對象必須在他的屬性值變化時觸發 PropertyChanged 事件. 下面是一個簡單的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class MyObject : INotifyPropertyChanged {  public event PropertyChangedEventHandler PropertyChanged;   string _firstName;  public string FirstName  {  get { return _firstName; }  set  {  if (value.Equals(_firstName, StringComparison.Ordinal))  {  // Nothing to do - the value hasn't changed;  return;  }  _firstName = value;  OnPropertyChanged();   }  }   void OnPropertyChanged([CallerMemberName] string propertyName = null)  {  var handler = PropertyChanged;  if (handler != null)  {  handler(this, new PropertyChangedEventArgs(propertyName));  }  } }

當某個 MyObject實例的FirstName 發生變化, OnPropertyChanged會被調用來觸發PropertyChanged 事件.

注意參數propertyName 使用了 CallMemberName 特性. 當OnPropertyChanged調用時參數爲空,  CallMemberName 特性會調用OnPropertyChanged方法的方法名.

Navigation

如今咱們已經明白如何建立一個page並顯示控件,接下來咱們討論下如何在page間導航跳轉。. Navigation能夠被看作一個後進先出,裏面全是Page對象的棧. 在應用程序中從一個page跳到另外一個page,只要在棧中壓入一個新的page對象;返回到以前的page則只要在棧中彈出當前的Page。Xamarin.Forms 中的導航使用 INavigation 接口

1
2
3
4
5
6
7
8
public interface INavigation {  Task PushAsync(Page page);  Task<Page> PopAsync();  Task PopToRootAsync();  Task PushModalAsync(Page page);  Task<Page> PopModalAsync(); }

這些方法都返回 Task對象,用於調用代碼確保push和pop page是否成功

Xamarin.Forms 內置了 NavigationPage 對象,實現了上面的接口用於管理page.  NavigationPage 類會屏幕上方在加入一個導航工具欄,上面會顯示一個標題,還有與平臺相應樣式的返回按鈕用於退回到前一個page。 下面的代碼展現如何在第一個page中使用 NavigationPage:

1
2
3
4
5
public static Page GetMainPage() {  var mainNav = new NavigationPage(new EmployeeListPage());  return mainNav; }

爲了在當前page中顯示LoginPage則須要調用 INavigation.PushAsync方法

1
await Navigation.PushAsync(new LoginPage());

當新的LoginPage 對象被壓入 Navigation 的棧中. 退回前一page, LoginPage 必須調用:

1
await Navigation.PopAsync();

模態的導航也是相似的. :

1
await Navigation.PushModalAsync(new LoginPage());

返回到調用頁的話, LoginPage必須使用:

1
await Navigation.PopModalAsync();
相關文章
相關標籤/搜索