MvvmCross TipCalc - 第 3 步:创建 iOS UI
TipCalc 教程 MvvmCross v3 - Hot Tuna 的第 3 步。
引言
本文是 MvvmCross
v3 - Hot Tuna! TipCalc
教程的第三步!
迄今为止...
我们开始的目标是创建一个应用程序,以帮助计算在餐厅应该留下多少小费。
我们计划基于此概念创建一个 UI

为了实现这一点,我们构建了一个“Core
”可移植类库项目,其中包含
- 我们的“业务逻辑” -
ICalculation
- 我们的 ViewModel -
TipViewModel
- 我们的 App,其中包含应用程序的连接,包括启动说明。
然后,我们添加了第一个用户界面 - 用于 Xamarin.Android

对于下一个项目,让我们转向 Xamarin.iOS
。
要创建 iPhone MvvmCross
UI,您可以使用 Visual Studio 项目模板向导,但在这里,我们将像 Core 和 Android 项目一样,从“空项目”开始构建一个新项目。
此外,为了使用 iPhone,我们现在将切换到 Mac 上的 Xamarin Studio 进行开发。
创建新的 iOS UI 项目
向您的解决方案添加一个新项目 - 一个名为 TipCalc.UI.Touch
的“Xamarin.iOS
”iPhone 应用程序。
在此之中,您会找到标准的 iOS 应用程序结构
- Resources 文件夹
info.plist
“配置”信息- AppDelegate.cs 类
- Main.cs 类
- MyViewController.cs 类
删除 MyViewController.cs
没有人真正需要 MyViewController
。 " align="top" src="https://codeproject.org.cn/script/Forums/Images/smiley_smile.gif" />
同样,删除 MyViewController.xib
(如果存在)。
添加引用
添加对 CoreCross、Binding 和 MvvmCross - PCL 版本的引用
为新项目添加对可移植库的引用
- Cirrious.CrossCore.dll
- 核心接口和概念,包括跟踪、IoC 和插件管理
- Cirrious.MvvmCross.Binding.dll
DataBinding
类 - 您主要从 C# 代码中使用它们
- Cirrious.MvvmCross.dll
- Mvvm 类 - 包括视图和 ViewModel 的基类
通常,这些文件位于类似 {SolutionRoot}/Libs/Mvx/Portable/ 的文件夹路径中。
添加对 CoreCross、Binding 和 MvvmCross - iOS 特定的版本的引用
为新项目添加对 Xamarin.iOS
特定库的引用
- Cirrious.CrossCore.Touch.dll
- Cirrious.MvvmCross.Binding.Touch.dll
- Cirrious.MvvmCross.Touch.dll
这些每个库都通过 iOS 特定的添加来扩展其 PCL 对等项的功能。
通常,这些文件位于类似 {SolutionRoot}/Libs/Mvx/Touch/ 的文件夹路径中。
另外,在同一个文件夹中,您还需要添加
添加对 TipCalc.Core.csproj 的引用
添加对您的 TipCalc.Core
项目的引用 - 这是我们在上一步创建的项目,其中包含
- 您的
Calculation
服务 - 您的
TipViewModel
- 您的 App 连接
添加 Setup 类
正如我们在 Android 构建过程中所说的那样,每个 MvvmCross UI 项目都需要一个 Setup 类。
此类位于我们 UI 项目的根命名空间(文件夹)中,负责初始化 MvvmCross
框架和您的应用程序,包括:
- 控制反转 (IoC) 系统
MvvmCross
数据绑定- 您的 App 及其
ViewModel
集合 - 您的 UI 项目及其 View 集合
其中大部分功能都是自动提供的。在您的 iOS UI 项目中,您只需要提供
- 您的 App - 您与业务逻辑和
ViewModel
内容的连接
对于 TipCalc
,Setup.cs 中需要的所有内容如下
using System;
using Cirrious.MvvmCross.Touch.Platform;
using TipCalc.Core;
using Cirrious.MvvmCross.Touch.Views.Presenters;
namespace TipCalc.UI.Touch
{
public class Setup : MvxTouchSetup
{
public Setup (MvxApplicationDelegate appDelegate, IMvxTouchViewPresenter presenter)
: base(appDelegate, presenter)
{
}
protected override Cirrious.MvvmCross.ViewModels.IMvxApplication CreateApp ()
{
return new App();
}
}
}
修改 AppDelegate 以使用 Setup
您的 AppDelegate
提供了一系列回调,iOS 用它们来通知您应用程序生命周期中的事件。
要在 MvvmCross
中使用此 AppDelegate
,我们需要
-
修改它,使其继承自
MvxApplicationDelegate
而不是UIApplicationDelegate
public partial class AppDelegate : MvxApplicationDelegate
-
修改它,以便在启动时调用的方法(
FinishedLaunching
)执行一些 UI 应用程序设置-
创建一个新的 presenter - 这个类将决定如何显示
View
- 在这个示例中,我们选择了一个“标准”的var presenter = new MvxTouchViewPresenter(this, window);
-
创建一个
Setup
实例并调用Initialize
var setup = new Setup(this, presenter); setup.Initialize();
-
在
Setup
完成后,使用 Mvx 控制反转容器来查找并Start
IMvxAppStart
对象var startup = Mvx.Resolve<IMvxAppStart>(); startup.Start();
-
总而言之,这看起来是这样的
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using Cirrious.MvvmCross.Touch.Platform;
using Cirrious.MvvmCross.Touch.Views.Presenters;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.CrossCore.IoC;
namespace TipCalc.UI.Touch
{
[Register("AppDelegate")]
public partial class AppDelegate : MvxApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
window = new UIWindow(UIScreen.MainScreen.Bounds);
var presenter = new MvxTouchViewPresenter(this, window);
var setup = new Setup(this, presenter);
setup.Initialize();
var startup = Mvx.Resolve<IMvxAppStart>();
startup.Start();
window.MakeKeyAndVisible();
return true;
}
}
}
添加您的 View
创建初始 UIViewController
创建一个 Views 文件夹
在此之中,添加一个新的“iPhone UIViewController
”,并将其命名为 TipView
。
这将生成
- TipView.cs
- TipView.designer.cs
- TipView.xib
编辑 XIB 布局
双击 XIB 文件。
这将在 xCode 中打开 XIB 编辑器。
就像我们在 Android 中所做的那样,我在这里不会深入探讨如何使用 XIB iOS 编辑器 - 相反,我只会介绍基础知识,我还会尝试为熟悉 XAML 的人提供一些比较。
从“对象库”拖放以添加
- 一些
UILabels
用于显示static
文本 - 这些类似于TextBlock
s - 一个
UITextField
用于编辑SubTotal
- 这类似于TextBox
- 一个
UISlider
用于编辑Generosity
- 这类似于ProgressBar
- 一个
UILabel
用于显示Tip
结果 - 这类似于TextBlock
通过拖放,您应该能够快速生成一个与以下类似的界面

在 XIB 编辑器中创建“outlets”
一旦您绘制好了 UI,您就可以将这些显示的 UI 字段链接到称为 outlets 的 ObjectiveC
变量。
完成此操作后,Xamarin Studio 中的 Xamarin.iOS
工具将自动检测这些更改,并将这些 ObjectiveC
字段映射回 iOS 应用中的 C# 属性。
要开始执行此操作,您需要从菜单选项“View” -> “Assistant Editor” -> “Show Assistant Editor”在 xCode 中打开“Assistant Editor”。这将显示一个带有 ObjectiveC
代码的小窗格 - 这就是“Assistant Editor”。
完成此操作后,您可以依次按住 Ctrl 键并单击(右键单击)SubTotal、Generosity 和 Tip 这三个字段。

对于每个字段
- 在设计器中按住 Ctrl 键单击 UI 字段
- 这将“弹出”一个列表,其中包含该字段可用的“outlets 和 actions”
- 找到标记为“New Referencing Outlet”的那个
- 单击“New Referencing Outlet”右侧的圆圈,然后将其拖到 Assistant Editor
- 将字段拖放到 Assistant Editor
- 它会要求您为 outlet 选项提供一个名称
按照此过程,您应该能够为这三个字段创建三个 ObjectiveC
outlet 变量
SubTotalTextField
GenerositySlider
TipLabel
完成后,保存您的 xCode 更改(使用 File 菜单)然后退出 xCode。
编辑 TipView.cs
回到 Xamarin Studio,您现在应该会看到 Xamarin 产品已更新 TipView.designer.cs 文件 - 它现在将包含三个带有这三个相同名称的 [Outlet] 属性
SubTotalTextField
GenerositySlider
TipLabel
关闭 TipView.designer.cs 文件 - 此文件是自动生成的局部类,Xamarin Studio 随时可以重新生成它 - 因此没有必要自己编辑它。
而是打开 TipView.cs - 它包含同一个局部类的可编辑部分。
由于我们希望 TipView
不仅是一个 UIViewController
,而且还是一个 Mvvm View,因此请更改 TipView
的继承,使其继承自 MvxViewController
。
public class TipView : MvxViewController
现在,为了将 TipView
链接到 TipViewModel
,请创建一个 public new TipViewModel ViewModel
属性 - 与您在 Xamarin.Android
中所做的完全一样
public new TipViewModel ViewModel
{
get { return (TipViewModel) base.ViewModel; }
set { base.ViewModel = value; }
}
要添加数据绑定代码,请转到 TipView
类中的 ViewDidLoad
方法。这是一个在 View
在 iOS 中加载后但在屏幕上显示之前调用的方法。
这使得 ViewDidLoad
成为调用一些数据绑定扩展方法的理想位置,这些方法将指定我们希望 UI 如何绑定到 ViewModel
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.Bind (this.TipLabel, (TipViewModel vm) => vm.Tip );
this.Bind (this.SubTotalTextField, (TipViewModel vm) => vm.SubTotal );
this.Bind (this.GenerositySlider, (TipViewModel vm) => vm.Generosity );
}
这段代码的作用是“在代码中”生成与我们在 Android 中“在 XML 中”生成的完全相同的数据绑定信息。
注意,在调用 this.Bind
之前,我们先调用 base.ViewDidLoad()
。这一点很重要,因为 base.ViewDidLoad()
是 MvvmCross
定位 TipViewModel
(这个 TipView
将绑定到它)的地方。
总而言之,这看起来是这样的
using System;
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.Binding.BindingContext;
using TipCalc.Core;
namespace TipCalc.UI.Touch
{
public partial class TipView : MvxViewController
{
public new TipViewModel ViewModel
{
get { return (TipViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}
public TipView () : base ("TipView", null)
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
this.CreateBinding (this.TipLabel).To( (TipViewModel vm) => vm.Tip ).Apply();
this.CreateBinding (this.SubTotalTextField).To( (TipViewModel vm) => vm.SubTotal ).Apply();
this.CreateBinding (this.GenerositySlider.To( (TipViewModel vm) => vm.Generosity ).Apply();
}
}
}
Xamarin.iOS 中的绑定
您无疑会注意到,iOS 中的数据绑定看起来与 Android 中的方式大不相同 - 也与您可能期望的 XAML 不同。
这是因为 iOS 中使用的 XIB 格式比 Android AXML 和 Windows XAML 中使用的 XML 格式更不易于手动操作和扩展 - 因此,使用 C# 而不是 XIB 来注册我们的绑定更有意义。
在本教程的这一部分中,我们所有的 iOS 绑定都如下所示
this.CreateBinding (this.TipLabel).To ((TipViewModel vm) => vm.Tip ).Apply();
这行代码的意思是
- 将
TipLabel
的默认绑定属性 - 碰巧是名为Text
的属性 - 绑定到
ViewModel
的Tip
属性
与 Android 一样,这默认情况下是一个 TwoWay
绑定 - 这与 XAML 开发人员可能期望看到的不同。
如果您想显式指定 TipLabel
属性使用 Text 而不是依赖默认值,那么您可以这样做:
this.CreateBinding (this.TipLabel).For(label => label.Text).To( (TipViewModel vm) => vm.Tip ).Apply();
在后续主题中,我们将涵盖更多关于 iOS 绑定的内容,包括更多关于绑定到非默认字段;其他基于代码的绑定代码机制;自定义绑定;使用 ValueConverters
;以及创建绑定的子视图。
iOS UI 完成!
此时,您应该能够运行您的应用程序。
当它启动时...您应该看到

这似乎工作得很完美,尽管您可能会注意到,如果您点击 SubTotal
属性并开始输入文本,那么您之后就无法关闭键盘。
这是 View
的职责 - 这是一个 UI 问题。所以我们可以只在 iOS UI 代码中,在这个 View 中修复它。例如,要在此处修复,您可以在 ViewDidLoad
方法的末尾添加一个手势识别器,如下所示
View.AddGestureRecognizer(new UITapGestureRecognizer(() => {
this.SubTotalTextField.ResignFirstResponder();
}));
继续...
我们可以做更多的事情来使这个用户界面更好,并使应用程序更丰富......但对于这个第一个应用程序,我们将暂时就此打住。
让我们继续 Windows!
文章
- MvvmCross TipCalc - 步骤 1:创建核心可移植应用程序
- MvvmCross TipCalc - 第 2 步:创建 Android UI
- MvvmCross TipCalc - 第 3 步:创建 iOS UI
- MvvmCross TipCalc - 第 4 步:创建 Windows Phone UI
- MvvmCross TipCalc - 第 5 步:创建 Windows Store UI
- MvvmCross TipCalc - 步骤 6:创建 WPF UI
- MvvmCross TipCalc - 回顾
历史
- 2013 年 3 月 22 日 - 首次提交