Xamarin.Forms 简介
2017-08-10 10:28
190 查看
跨平台用户界面入门
可离线查看的 PDF
下载
PDF
相关 API:
Xamarin.Forms
你对此内容有什么想法,请告知我们
上次更新时间: 十二月 2016
Xamarin.Forms 是本机支持的跨平台抽象 UI 工具包,让开发人员能够轻松创建可在 Android、iOS、Windows 和 Windows Phone 之间共享的用户界面。 使用目标平台的本机控件即可呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留相应的界面外观。 本文介绍了 Xamarin.Forms 以及如何开始使用它编写应用程序。
Xamarin.Forms 框架让开发人员能够快速创建跨平台用户界面。 它为用户界面提供自己的抽象,用户界面可使用 iOS、Android、Windows 或 Windows Phone 上的本机控件呈现。 这意味着应用程序可以共享大部分用户界面代码,同时保留目标平台的本机外观。
Xamarin.Forms 能让原型应用程序随时间推移迅速演变为复杂应用程序。 由于 Xamarin.Forms 应用程序是本机应用程序,因此没有其他工具包(如浏览器沙盒、API 限制或性能不佳)的限制。 使用 Xamarin.Forms 编写的应用程序能够利用基础平台的任何 API 或功能,包括(但不限于) iOS 上的 CoreMotion、PassKit 和 StoreKit;Android 上的 NFC 和 Google Play Services;以及 Windows 上的磁贴。 此外,创建应用程序时,还可以使用
Xamarin.Forms 创建应用程序用户界面的一部分,使用本机 UI 工具包创建应用程序用户界面的其他部分。
Xamarin.Forms 应用程序采用与传统跨平台应用程序相同的构建方式。 最常用的方法是使用可移植库或共享项目来存放共享代码,并创建会使用共享代码的特定于平台的应用程序。
在 Xamarin.Forms 中创建用户界面可以采用两种方法。 第一种方法是完全使用 C# 源代码创建 UI。 第二种方法是使用Extensible Application Markup Language (XAML)(一种声明性标记语言)来描述用户界面。 有关 XAML 的详细信息,请参阅XAML
基础。
本文讨论 Xamarin.Forms 框架的基础知识,包括以下主题:
检查
Xamarin.Forms 应用程序。
如何使用
Xamarin.Forms 页面和控件。
如何显示数据列表。
如何设置数据绑定。
如何在页面之间导航。
后续步骤。
在 Xamarin Studio 和 Visual Studio 中,可以使用默认的 Xamarin.Forms 应用程序模板创建最简单的 Xamarin.Forms 解决方案,并向用户显示文本。 如果运行该应用程序,它应类似于以下屏幕截图:
屏幕截图中的每个屏幕对应于 Xamarin.Forms 中的一个页面。
Android 表示为一个活动,在 iOS 中表示为一个视图控制器,在 Windows 通用平台 (UWP) 中则表示为一个页面。 以上屏幕截图中的示例实例化
为了最大限度重用启动代码,Xamarin.Forms 应用程序有一个名为
此代码实例化一个新的
若要在应用程序内部使用此
Xamarin.Forms 框架并提供
初始化步骤因平台而异,此内容将在以下部分讨论。
若要在 iOS 中启动 Xamarin.Forms 初始页面,平台项目应包括
通过调用
iOS 的 Xamarin.Forms 实现加载到应用程序。
若要在 Android 中启动 Xamarin.Forms 初始页面,平台项目应包括可使用
通过调用
应用程序之前,将特定于 Android 的 Xamarin.Forms 实现加载到应用程序。
在 Windows 运行时应用程序中,可从
这会将特定于 Windows Phone 的 Xamarin.Forms 实现加载到应用程序中。 可通过
可通过
Xamarin.Forms 还支持 Windows 8.1。 有关如何配置此项目类型的信息,请参阅设置
Windows 项目。
在通用 Windows 平台 (UWP) 应用程序中,可从
这会将特定于 UWP 的 Xamarin.Forms 实现加载到应用程序。 可通过
可通过
可使用 4 个主要控件组创建 Xamarin.Forms 应用程序的用户界面。
页面 - Xamarin.Forms 页呈现跨平台移动应用程序屏幕。 有关页面的详细信息,请参阅 Xamarin.Forms
页面。
布局 - Xamarin.Forms 布局是用于将视图组合到逻辑结构的容器。 有关布局的详细信息,请参阅 Xamarin.Forms
布局。
视图 - Xamarin.Forms 视图是显示在用户界面上的控件,如标签、按钮和文本输入框。 有关视图的详细信息,请参阅Xamarin.Forms
视图。
单元格 - Xamarin.Forms 单元格是专门用于列表中的项的元素,描述列表中每个项的绘制方式。 有关单元格的详细信息,请参阅 Xamarin.Forms
单元格。
在运行时,每个控件都会映射到其本身的本机等效项(即呈现的内容)。
控件在布局内部进行托管。 现在检查
根据添加顺序,以垂直方式或水平方式逐个放置每个子元素。
以下 XAML 代码举例说明了如何使用
以下代码示例显示相应的 C# 代码:
默认情况下,
可以将
XAML 代码示例所示:
以下代码示例显示相应的 C# 代码:
以下屏幕截图显示布局结果:
可通过
以下代码示例显示相应的 C# 代码:
以下屏幕截图显示布局结果:
有关
-
以下代码示例演示一个简单的
以下屏幕截图显示生成的
有关
以下代码示例演示
可按如下代码示例所示填充
可以创建一个绑定以设置
这会创建一个绑定,指定
有关绑定到自定义类的详细信息,请参阅 ListView
数据源。
为响应用户触摸
当包含在
每个平台实现内置后退导航的方法都各不相同。 有关详细信息,请参阅导航。
有关
交互性。
通过子类化
以下屏幕截图所示的单元格由一个
若要创建此自定义布局,应子类化
此段代码执行下列任务:
添加
若要深入了解数据绑定,请参阅数据绑定。
创建垂直方向的
创建
使用水平方向排列其子级。
创建好自定义单元格后,可以通过将其包装在
此代码为
可使用
有关自定义单元格的外观的详细信息,请参阅单元格的外观。
以下代码示例演示上一部分中
XAML 等效项:
此 XAML 定义包含
可通过
在
数据绑定连接两个对象,即源和目标。 源对象提供数据。 目标对象使用(并经常显示)来自源对象的数据。 例如,
下图说明了这种绑定关系:
数据绑定的主要优点是让你无需再担心视图和数据源之间的数据同步。 幕后的绑定框架源会将源对象中的更改自动推送到目标对象,且目标对象中的更改可选择性地推送回源对象。
创建数据绑定只需两个步骤:
目标对象的
必须在目标和源之间建立绑定。 在 XAML 中,此过程可通过使用
在 C# 中,此过程可通过
若要深入了解数据绑定,请参阅数据绑定基本知识。
以下代码示例说明如何在 XAML 中执行数据绑定:
在
对象的
同样,如果更改了
这称为双向绑定。 为了使双向绑定发挥作用,模型类必须实现
尽管可以在 XAML 中设置
虽然可以分别设置每个目标对象的
因此,当
以下代码示例说明如何在 C# 中执行数据绑定:
向
实例化
同样,如果更改了
这称为双向绑定。 为了使双向绑定发挥作用,模型类必须实现
使用下列语法可直接绑定到
使用点语法指示 Xamarin.Forms 使用
如果
创建绑定后,默认情况下目标对象只接收源对象的值。 若要使 UI 与数据源同步,当源对象发生更改时,必须通过一种方法来通知目标对象。
当它的某个属性更新为新值时,实现
当
为了避免不必要的事件触发,如果属性值没有发生更改,则不引发
请注意,在
这可确保当使用
Xamarin.Forms 提供多种不同的页导航体验,具体取决于使用的
对于
分层导航
模式导航
有关详细信息,请参阅导航。
此类将导航实现为
(LIFO) 堆栈。
在分层导航中,使用
若要从一页移动到另一页,应用程序会将新页推送到导航堆栈中,在堆栈中,该页会变为活动页。 若要返回到前一页,应用程序会从导航堆栈弹出当前页,而使最顶层的页成为活动页。
添加到导航堆栈中的第一页称为应用程序的根页,以下代码示例显示了实现此过程的方法:
若要导航到
这会将新的
通过设备上的返回按钮(无论是设备上的物理按钮还是屏幕按钮),可以从导航堆栈中弹出活动页。 若要以编程方式返回到前一页,
有关分层导航的详细信息,请参阅分层导航。
Xamarin.Forms 支持模式页面。 模式页面鼓励用户完成独立任务,在完成或取消该任务之前,不允许导航离开该任务。
模式页面可以是 Xamarin.Forms 支持的任何
若要显示模式页面,应用程序会将页面推送到导航堆栈中,在堆栈中,该页会变为活动页。 若要返到回前一页,应用程序会从导航堆栈弹出当前页面,而使最顶层的页成为活动页。
可以由任何
也可使用
但是,在模式导航中没有执行模式堆栈操作或弹出到根页的概念。 这是因为基础平台普遍都不支持这些操作。
执行模式页面导航无需具有
若要以模式方式导航到
这会将
通过设备上的返回按钮(无论是设备上的物理按钮还是屏幕按钮),可以从导航堆栈中弹出活动页。 若要以编程方式返回原始页,
这会从导航堆栈中删除
有关模式导航的详细信息,请参阅模式页面。
本文介绍了如何开始编写 Xamarin.Forms 应用程序。 建议的后续步骤包括了解以下功能:
控件模板让你在运行时能够轻松设计或重新设计应用程序页面的主题。 有关详细信息,请参阅控件模板。
数据模板让你可以在支持的控件上定义数据表示形式。 有关详细信息,请参阅数据模板。
共享代码可通过
有关详细信息,请参阅通过 DependencyService 访问本机功能。
Xamarin.Forms 具有简单的消息传送服务,用于发送和接收消息,减少两个类之间的耦合。 有关详细信息,请参阅通过
MessagingCenter 发布和订阅。
通过
有关详细信息,请参阅自定义呈现器。
还可以自定义每个平台上的本机控件的效果。 通过子类化
Xamarin.Forms 控件中使用。 有关详细信息,请参阅效果。
此外,也可以阅读 Charles Petzold 撰写的 Creating Mobile Apps with Xamarin.Forms(使用 Xamarin.Forms 创建移动应用),了解有关 Xamarin.Forms 的详细信息。 有关详细信息,请参阅使用
Xamarin.Forms 创建移动应用。
本文介绍了 Xamarin.Forms 以及如何开始使用它编写应用程序。 Xamarin.Forms 是本机支持的跨平台抽象 UI 工具包,让开发人员能够轻松创建可在 Android、iOS、Windows 和 Windows Phone 之间共享的用户界面。 使用目标平台的本机控件即可呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留相应的界面外观。
可离线查看的 PDF
下载
相关 API:
Xamarin.Forms
你对此内容有什么想法,请告知我们
上次更新时间: 十二月 2016
Xamarin.Forms 是本机支持的跨平台抽象 UI 工具包,让开发人员能够轻松创建可在 Android、iOS、Windows 和 Windows Phone 之间共享的用户界面。 使用目标平台的本机控件即可呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留相应的界面外观。 本文介绍了 Xamarin.Forms 以及如何开始使用它编写应用程序。
概述
Xamarin.Forms 框架让开发人员能够快速创建跨平台用户界面。 它为用户界面提供自己的抽象,用户界面可使用 iOS、Android、Windows 或 Windows Phone 上的本机控件呈现。 这意味着应用程序可以共享大部分用户界面代码,同时保留目标平台的本机外观。Xamarin.Forms 能让原型应用程序随时间推移迅速演变为复杂应用程序。 由于 Xamarin.Forms 应用程序是本机应用程序,因此没有其他工具包(如浏览器沙盒、API 限制或性能不佳)的限制。 使用 Xamarin.Forms 编写的应用程序能够利用基础平台的任何 API 或功能,包括(但不限于) iOS 上的 CoreMotion、PassKit 和 StoreKit;Android 上的 NFC 和 Google Play Services;以及 Windows 上的磁贴。 此外,创建应用程序时,还可以使用
Xamarin.Forms 创建应用程序用户界面的一部分,使用本机 UI 工具包创建应用程序用户界面的其他部分。
Xamarin.Forms 应用程序采用与传统跨平台应用程序相同的构建方式。 最常用的方法是使用可移植库或共享项目来存放共享代码,并创建会使用共享代码的特定于平台的应用程序。
在 Xamarin.Forms 中创建用户界面可以采用两种方法。 第一种方法是完全使用 C# 源代码创建 UI。 第二种方法是使用Extensible Application Markup Language (XAML)(一种声明性标记语言)来描述用户界面。 有关 XAML 的详细信息,请参阅XAML
基础。
本文讨论 Xamarin.Forms 框架的基础知识,包括以下主题:
检查
Xamarin.Forms 应用程序。
如何使用
Xamarin.Forms 页面和控件。
如何显示数据列表。
如何设置数据绑定。
如何在页面之间导航。
后续步骤。
检查 Xamarin.Forms 应用程序
在 Xamarin Studio 和 Visual Studio 中,可以使用默认的 Xamarin.Forms 应用程序模板创建最简单的 Xamarin.Forms 解决方案,并向用户显示文本。 如果运行该应用程序,它应类似于以下屏幕截图:屏幕截图中的每个屏幕对应于 Xamarin.Forms 中的一个页面。
Page在
Android 表示为一个活动,在 iOS 中表示为一个视图控制器,在 Windows 通用平台 (UWP) 中则表示为一个页面。 以上屏幕截图中的示例实例化
ContentPage对象,并使用该对象显示
Label。
为了最大限度重用启动代码,Xamarin.Forms 应用程序有一个名为
App的单个类,该类负责实例化第一个将要显示的
Page。
App类的示例可以在以下代码中看到:
public class App : Application { public App () { MainPage = new ContentPage { Content = new Label { Text = "Hello, Forms !", VerticalOptions = LayoutOptions.CenterAndExpand, HorizontalOptions = LayoutOptions.CenterAndExpand, } }; } }[/code]
此代码实例化一个新的
ContentPage对象,该对象将在页面上垂直和水平居中显示单个
Label。
在每个平台上启动 Xamarin.Forms 初始页面
若要在应用程序内部使用此 Page,每个平台应用程序启动时必须初始化
Xamarin.Forms 框架并提供
ContentPage的一个实例。
初始化步骤因平台而异,此内容将在以下部分讨论。
iOS
若要在 iOS 中启动 Xamarin.Forms 初始页面,平台项目应包括 AppDelegate类(该类从
Xamarin.Forms.Platform.iOS.FormsApplicationDelegate类继承),如以下代码示例所示:
[Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init (); LoadApplication (new App ()); return base.FinishedLaunching (app, options); } }[/code]
通过调用
Init方法,
FinishedLoading替代初始化 Xamarin.Forms 框架。 这会导致在调用将根视图控制器设置为
LoadApplication方法之前,将特定于
iOS 的 Xamarin.Forms 实现加载到应用程序。
Android
若要在 Android 中启动 Xamarin.Forms 初始页面,平台项目应包括可使用 MainLauncher属性创建
Activity的代码,且具有从
FormsApplicationActivity类继承的活动,如以下代码示例所示:
namespace HelloXamarinFormsWorld.Android { [Activity(Label = "HelloXamarinFormsWorld", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsApplicationActivity { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); Xamarin.Forms.Forms.Init(this, bundle); LoadApplication (new App ()); } } }[/code]
通过调用
Init方法,
OnCreate替代初始化 Xamarin.Forms 框架。 这会导致在加载 Xamarin.Forms
应用程序之前,将特定于 Android 的 Xamarin.Forms 实现加载到应用程序。
Windows Phone 8.1 (WinRT)
在 Windows 运行时应用程序中,可从 App类调用初始化 Xamarin.Forms 框架的
Init方法:
Xamarin.Forms.Forms.Init (e); if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) { ... }[/code]
这会将特定于 Windows Phone 的 Xamarin.Forms 实现加载到应用程序中。 可通过
MainPage类启动 Xamarin.Forms 初始页面,如以下代码示例所示:
public partial class MainPage { public MainPage() { this.InitializeComponent(); this.NavigationCacheMode = NavigationCacheMode.Required; this.LoadApplication(new HelloXamarinFormsWorld.App()); } }[/code]
可通过
LoadApplication方法加载 Xamarin.Forms 应用程序。
Xamarin.Forms 还支持 Windows 8.1。 有关如何配置此项目类型的信息,请参阅设置
Windows 项目。
通用 Windows 平台
在通用 Windows 平台 (UWP) 应用程序中,可从 App类调用初始化 Xamarin.Forms 框架的
Init方法:
Xamarin.Forms.Forms.Init (e); if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) { ... }[/code]
这会将特定于 UWP 的 Xamarin.Forms 实现加载到应用程序。 可通过
MainPage类启动 Xamarin.Forms 初始页面,如以下代码示例所示:
public partial class MainPage { public MainPage() { this.InitializeComponent(); this.LoadApplication(new HelloXamarinFormsWorld.App()); } }[/code]
可通过
LoadApplication方法加载 Xamarin.Forms 应用程序。
视图和布局
可使用 4 个主要控件组创建 Xamarin.Forms 应用程序的用户界面。页面 - Xamarin.Forms 页呈现跨平台移动应用程序屏幕。 有关页面的详细信息,请参阅 Xamarin.Forms
页面。
布局 - Xamarin.Forms 布局是用于将视图组合到逻辑结构的容器。 有关布局的详细信息,请参阅 Xamarin.Forms
布局。
视图 - Xamarin.Forms 视图是显示在用户界面上的控件,如标签、按钮和文本输入框。 有关视图的详细信息,请参阅Xamarin.Forms
视图。
单元格 - Xamarin.Forms 单元格是专门用于列表中的项的元素,描述列表中每个项的绘制方式。 有关单元格的详细信息,请参阅 Xamarin.Forms
单元格。
在运行时,每个控件都会映射到其本身的本机等效项(即呈现的内容)。
控件在布局内部进行托管。 现在检查
StackLayout类,该类实现常用的布局。
StackLayout
StackLayout在屏幕上自动排列控件而不考虑屏幕大小,从而简化了跨平台应用程序开发。
根据添加顺序,以垂直方式或水平方式逐个放置每个子元素。
StackLayout使用的空间大小取决于
HorizontalOptions和
VerticalOptions属性的设置方式,但默认情况下,
StackLayout尝试使用整个屏幕。
以下 XAML 代码举例说明了如何使用
StackLayout排列三个
Label控件:
<?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>[/code]
以下代码示例显示相应的 C# 代码:
public class StackLayoutExample : ContentPage { public StackLayoutExample() { Padding = new Thickness(20); var red = new Label { Text = "Stop", BackgroundColor = Color.Red, FontSize = 20 }; var yellow = new Label { Text = "Slow down", BackgroundColor = Color.Yellow, FontSize = 20 }; var green = new Label { Text = "Go", BackgroundColor = Color.Green, FontSize = 20 }; Content = new StackLayout { Spacing = 10, Children = { red, yellow, green } }; } }[/code]
默认情况下,
StackLayout采用垂直方向,如以下屏幕截图所示:
可以将
StackLayout更改为水平方向,如以下
XAML 代码示例所示:
<?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>[/code]
以下代码示例显示相应的 C# 代码:
public class StackLayoutExample: ContentPage { public StackLayoutExample() { // Code that creates labels removed for clarity Content = new StackLayout { Spacing = 10, VerticalOptions = LayoutOptions.End, Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.Start, Children = { red, yellow, green } }; } }[/code]
以下屏幕截图显示布局结果:
可通过
HeightRequest和
WidthRequest属性设置控件大小,如以下 XAML 代码示例所示:
<?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>[/code]
以下代码示例显示相应的 C# 代码:
var red = new Label { Text = "Stop", BackgroundColor = Color.Red, FontSize = 20, WidthRequest = 100 }; var yellow = new Label { Text = "Slow down", BackgroundColor = Color.Yellow, FontSize = 20, WidthRequest = 100 }; var green = new Label { Text = "Go", BackgroundColor = Color.Green, FontSize = 20, WidthRequest = 200 }; Content = new StackLayout { Spacing = 10, VerticalOptions = LayoutOptions.End, Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.Start, Children = { red, yellow, green } };[/code]
以下屏幕截图显示布局结果:
有关
StackLayout类的详细信息,请参阅 StackLayout。
Xamarin.Forms 中的列表
ListView控件负责在屏幕上显示项集合
-
ListView中的每一个项都包含在单个单元格中。 默认情况下,
ListView使用内置
TextCell模板并呈现单行文本。
以下代码示例演示一个简单的
ListView示例:
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 } };[/code]
以下屏幕截图显示生成的
ListView:
有关
ListView控件的详细信息,请参阅 ListView。
绑定到自定义类
ListView控件还可以通过默认的
TextCell模板显示自定义对象。
以下代码示例演示
TodoItem类:
public class TodoItem { public string Name { get; set; } public bool Done { get; set; } }[/code]
可按如下代码示例所示填充
ListView控件:
listView.ItemsSource = 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 } };[/code]
可以创建一个绑定以设置
ListView要显示的
TodoItem属性类型,如以下代码示例所示:
listView.ItemTemplate = new DataTemplate(typeof(TextCell)); listView.ItemTemplate.SetBinding(TextCell.TextProperty, "Name");[/code]
这会创建一个绑定,指定
TodoItem.Name属性的路径,并生成前面显示的屏幕截图。
有关绑定到自定义类的详细信息,请参阅 ListView
数据源。
选择 ListView 中的项
为响应用户触摸 ListView中的单元格,应处理
ItemSelected事件,如以下代码示例所示:
listView.ItemSelected += async (sender, e) => { await DisplayAlert("Tapped!", e.SelectedItem + " was tapped.", "OK"); };[/code]
当包含在
NavigationPage中时,
PushAsync方法可用来打开具有内置后退导航的新页面。
ItemSelected事件可以访问通过
e.SelectedItem属性与单元格关联的对象,将其绑定到新页面并使用
PushAsync显示新页面,如以下代码示例所示:
listView.ItemSelected += async (sender, e) => { var todoItem = (TodoItem)e.SelectedItem; var todoPage = new TodoItemPage(todoItem); // so the new page shows correct data await Navigation.PushAsync(todoPage); };[/code]
每个平台实现内置后退导航的方法都各不相同。 有关详细信息,请参阅导航。
有关
ListView选择的详细信息,请参阅 ListView
交互性。
自定义单元格的外观
通过子类化 ViewCell类,并将该类的类型设置为
ListView的
ItemTemplate属性,可以自定义单元格的外观。
以下屏幕截图所示的单元格由一个
Image和两个
Label控件组成:
若要创建此自定义布局,应子类化
ViewCell类,如以下代码示例所示:
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; } }[/code]
此段代码执行下列任务:
添加
Image控件并将其绑定到
Employee对象的
ImageUri属性。
若要深入了解数据绑定,请参阅数据绑定。
创建垂直方向的
StackLayout来存放两个
Label控件。
Label控件被绑定到
DisplayName和
Employee对象的
创建
StackLayout用于托管现有的
Image和
StackLayout。
使用水平方向排列其子级。
创建好自定义单元格后,可以通过将其包装在
DataTemplate中由
ListView控件使用,如以下代码示例所示:
List<Employee> myListOfEmployeeObjects = GetAListOfAllEmployees(); var listView = new ListView { RowHeight = 40 }; listView.ItemsSource = myListOfEmployeeObjects; listView.ItemTemplate = new DataTemplate(typeof(EmployeeCell));[/code]
此代码为
ListView提供
Employee的
List。
可使用
EmployeeCell类呈现每个单元格。
ListView将
Employee对象作为其
BindingContext传递给
EmployeeCell。
有关自定义单元格的外观的详细信息,请参阅单元格的外观。
使用 XAML 创建和自定义列表
以下代码示例演示上一部分中 ListView的
XAML 等效项:
<?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>[/code]
此 XAML 定义包含
ListView的
ContentPage。
可通过
ItemsSource属性设置
ListView的数据源。
在
ListView.ItemTemplate元素内定义
ItemsSource中每一行的布局。
数据绑定
数据绑定连接两个对象,即源和目标。 源对象提供数据。 目标对象使用(并经常显示)来自源对象的数据。 例如,Label(目标对象)通常会将其
Text属性绑定到源对象中的公共
string属性。
下图说明了这种绑定关系:
数据绑定的主要优点是让你无需再担心视图和数据源之间的数据同步。 幕后的绑定框架源会将源对象中的更改自动推送到目标对象,且目标对象中的更改可选择性地推送回源对象。
创建数据绑定只需两个步骤:
目标对象的
BindingContext属性必须设置为源。
必须在目标和源之间建立绑定。 在 XAML 中,此过程可通过使用
Binding标记扩展实现。
在 C# 中,此过程可通过
SetBinding方法实现。
若要深入了解数据绑定,请参阅数据绑定基本知识。
XAML
以下代码示例说明如何在 XAML 中执行数据绑定:<Entry Text="{Binding FirstName}" ... />[/code]
在
Entry.Text属性和源
对象的
FirstName属性之间建立绑定。
Entry控件中所做的更改将自动传播到
employeeToDisplay对象。
同样,如果更改了
employeeToDisplay.FirstName属性,Xamarin.Forms 绑定引擎也会更新
Entry控件的内容。
这称为双向绑定。 为了使双向绑定发挥作用,模型类必须实现
INotifyPropertyChanged接口。
尽管可以在 XAML 中设置
EmployeeDetailPage类的
BindingContext属性,但此处在代码隐藏中设置
Employee对象的实例:
public EmployeeDetailPage(Employee employee) { InitializeComponent(); this.BindingContext = employee; }[/code]
虽然可以分别设置每个目标对象的
BindingContext属性,但没有必要。
BindingContext是特殊属性,其所有子级都会继承该属性。
因此,当
ContentPage上的
BindingContext设置为
Employee实例时,
ContentPage的所有子级都具有相同的
BindingContext,并且都可绑定到
Employee对象的公共属性。
C#
以下代码示例说明如何在 C# 中执行数据绑定:public EmployeeDetailPage(Employee employeeToDisplay) { this.BindingContext = employeeToDisplay; var firstName = new Entry() { HorizontalOptions = LayoutOptions.FillAndExpand }; firstName.SetBinding(Entry.TextProperty, "FirstName"); ... }[/code]
向
ContentPage构造函数传递
Employee对象的一个实例,并将
BindingContext设置为要绑定到的对象。
实例化
Entry控件,并在
Entry.Text属性和源对象的
FirstName属性之间设置绑定。
Entry控件中所做的更改将自动传播到
employeeToDisplay对象。
同样,如果更改了
employeeToDisplay.FirstName属性,Xamarin.Forms 绑定引擎也会更新
Entry控件的内容。
这称为双向绑定。 为了使双向绑定发挥作用,模型类必须实现
INotifyPropertyChanged接口。
SetBinding方法采用两个参数。 第一个参数指定绑定类型的信息。 第二个参数提供绑定内容或绑定方式的信息。 大多数情况下,第二个参数只是一个字符串,持有
BindingContext上的属性名称。
使用下列语法可直接绑定到
BindingContext:
someLabel.SetBinding(Label.TextProperty, new Binding("."));[/code]
使用点语法指示 Xamarin.Forms 使用
BindingContext(而非
BindingContext上的属性)作为数据源。
如果
BindingContext是简单类型(例如
string或
int),此语法非常有用。
属性更改通知
创建绑定后,默认情况下目标对象只接收源对象的值。 若要使 UI 与数据源同步,当源对象发生更改时,必须通过一种方法来通知目标对象。 INotifyPropertyChanged接口就提供了这种机制。 当基础属性值发生更改时,实现此接口可以通知任何数据绑定控件。
当它的某个属性更新为新值时,实现
INotifyPropertyChanged的对象必须引发
PropertyChanged事件,如以下代码示例所示:
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)); } } }[/code]
当
MyObject.FirstName属性发生更改时,会调用
OnPropertyChanged法,从而引发
PropertyChanged事件。
为了避免不必要的事件触发,如果属性值没有发生更改,则不引发
PropertyChanged事件。
请注意,在
OnPropertyChanged方法中,
propertyName参数标有
CallerMemberName属性。
这可确保当使用
null值调用
OnPropertyChanged方法时,
CallerMemberName属性提供调用
OnPropertyChanged的方法的名称。
导航
Xamarin.Forms 提供多种不同的页导航体验,具体取决于使用的 Page类型。
对于
ContentPage实例,提供两种导航体验:
分层导航
模式导航
CarouselPage
MasterDetailPage和
TabbedPage类提供替代导航体验。
有关详细信息,请参阅导航。
分层导航
NavigationPage类提供分层导航体验,用户可以随心所欲地向前或向后导航页面。
此类将导航实现为
Page对象的后进先出
(LIFO) 堆栈。
在分层导航中,使用
NavigationPage类在
ContentPage对象的堆栈内进行导航。
若要从一页移动到另一页,应用程序会将新页推送到导航堆栈中,在堆栈中,该页会变为活动页。 若要返回到前一页,应用程序会从导航堆栈弹出当前页,而使最顶层的页成为活动页。
添加到导航堆栈中的第一页称为应用程序的根页,以下代码示例显示了实现此过程的方法:
public App () { MainPage = new NavigationPage(new EmployeeListPage()); }[/code]
若要导航到
LoginPage,需要调用当前页的
Navigation属性上的
PushAsync方法,如以下代码示例所示:
await Navigation.PushAsync(new LoginPage());[/code]
这会将新的
LoginPage对象推送到导航堆栈中,在堆栈中,它成为活动页。
通过设备上的返回按钮(无论是设备上的物理按钮还是屏幕按钮),可以从导航堆栈中弹出活动页。 若要以编程方式返回到前一页,
LoginPage实例必须调用
PopAsync方法,如以下代码示例所示:
await Navigation.PopAsync();[/code]
有关分层导航的详细信息,请参阅分层导航。
模式导航
Xamarin.Forms 支持模式页面。 模式页面鼓励用户完成独立任务,在完成或取消该任务之前,不允许导航离开该任务。模式页面可以是 Xamarin.Forms 支持的任何
Page类型。
若要显示模式页面,应用程序会将页面推送到导航堆栈中,在堆栈中,该页会变为活动页。 若要返到回前一页,应用程序会从导航堆栈弹出当前页面,而使最顶层的页成为活动页。
可以由任何
Page派生类型上的
Navigation属性公开模式导航方法。
也可使用
Navigation属性公开
ModalStack属性,并从中获得导航堆栈中的模式页面。
但是,在模式导航中没有执行模式堆栈操作或弹出到根页的概念。 这是因为基础平台普遍都不支持这些操作。
执行模式页面导航无需具有
NavigationPage实例。
若要以模式方式导航到
LoginPage,需要调用当前页的
Navigation属性上的
PushModalAsync方法,如以下代码示例所示:
await Navigation.PushModalAsync(new LoginPage());[/code]
这会将
LoginPage实例推送到导航堆栈中,在堆栈中,它成为活动页。
通过设备上的返回按钮(无论是设备上的物理按钮还是屏幕按钮),可以从导航堆栈中弹出活动页。 若要以编程方式返回原始页,
LoginPage实例必须调用
PopModalAsync方法,如以下代码示例所示:
await Navigation.PopModalAsync();[/code]
这会从导航堆栈中删除
LoginPage实例,而使最顶层的页成为活动页。
有关模式导航的详细信息,请参阅模式页面。
后续步骤
本文介绍了如何开始编写 Xamarin.Forms 应用程序。 建议的后续步骤包括了解以下功能:控件模板让你在运行时能够轻松设计或重新设计应用程序页面的主题。 有关详细信息,请参阅控件模板。
数据模板让你可以在支持的控件上定义数据表示形式。 有关详细信息,请参阅数据模板。
共享代码可通过
DependencyService类访问本机功能。
有关详细信息,请参阅通过 DependencyService 访问本机功能。
Xamarin.Forms 具有简单的消息传送服务,用于发送和接收消息,减少两个类之间的耦合。 有关详细信息,请参阅通过
MessagingCenter 发布和订阅。
通过
Renderer类可以在每个平台上以不同方式呈现每个页面、布局和控件,反过来又可以创建本机控件,在屏幕上排列该控件,并添加共享代码中指定的行为。 开发人员可以实现自定义
Renderer类,以自定义控件的外观和/或行为。
有关详细信息,请参阅自定义呈现器。
还可以自定义每个平台上的本机控件的效果。 通过子类化
PlatformEffect控件在特定于平台的项目中创建效果,并将其附加到相应的
Xamarin.Forms 控件中使用。 有关详细信息,请参阅效果。
此外,也可以阅读 Charles Petzold 撰写的 Creating Mobile Apps with Xamarin.Forms(使用 Xamarin.Forms 创建移动应用),了解有关 Xamarin.Forms 的详细信息。 有关详细信息,请参阅使用
Xamarin.Forms 创建移动应用。
摘要
本文介绍了 Xamarin.Forms 以及如何开始使用它编写应用程序。 Xamarin.Forms 是本机支持的跨平台抽象 UI 工具包,让开发人员能够轻松创建可在 Android、iOS、Windows 和 Windows Phone 之间共享的用户界面。 使用目标平台的本机控件即可呈现用户界面,从而让 Xamarin.Forms 应用程序为每个平台保留相应的界面外观。
相关文章推荐
- Xamarin.Forms 简介
- Xamarin.Forms教程下载安装Xamarin.iOS
- UrhoSharp Xamarin.Forms 开发入门
- .NET Standard@Xamarin.Forms
- Xamarin.Forms 用户界面
- Xamarin.Forms教程下载安装JDK配置环境变量
- Xamarin.Forms+Prism(1)—— 开发准备
- Xamarin.Forms bug? System.ObjectDisposedException: Cannot access a disposed object
- Xamarin.Forms 用户界面——控件——Text
- Xamarin.forms:(Rg.Plugins.Popup)Nuget包的使用小案例
- Xamarin.Forms的ActivityIndicator和ProgressBar比较
- Xamarin.Forms新手指南
- Xamarin.Forms之库不兼容现象记录
- Xamarin.Forms的基本页面和基本视图
- Xamarin--简介
- Xamarin.Forms 用户界面
- Xamarin.Forms之Frame布局
- Xamarin.Forms的相对布局RelativeLayout
- Xamarin.Forms之异步
- Xamarin.Forms之Effects的使用