跨平台开发框架 MvvmCross 初体验
跨平台开发框架 MvvmCross 初体验
MvvmCross 的特点
- 尽量使用可移植类库进行编码, 可以包括 视图模型 (ViewModel) 、 模型 (Model) 、 服务 (Service) 甚至界面 (View)
- 使用 MVVM 模式和数据绑定 (Data Binding) 技术
- 使用目标平台的本地化界面
- 框架的任何部分都可以被重写
准备使用 MvvmCross
推荐的方式是建立自己的 git 库, 然后将 MvvmCross 添加为 SubModule , 有自己 github 账户的话就更方便了。 我的是:MvvmCross-Learning
MvvmCross 的文档主要是它在 github 上面的 wiki , 另外就是 MvvmCross-Tutorials, 有大量的示例代码, 可以说是掌握 MvvmCross 的重要资料。
将 MvvmCross 和 MvvmCross-Tutorials 两个库添加为 submodule ,方便进行源代码调试和学习。
MvvmCross 的代码同步好了之后, 默认的分支是 v3.0, 基于 PCL 104, 在 windows 系统上, 可以直接编译; 而在 Mac 系统上, 需要切换到分支 v3.1 , 这个分支基于 PCL 158, 可以在 Mac 系统上进行编译。
使用 MvvmCross 创建跨平台应用
MvvmCross 应用至少包含两个项目, 一个是基于 PCL 的 Core 项目, 包含所有的视图模型、 服务以及应用程序逻辑代码; 一个是目标平台的界面项目, 包含目标平台的视图以及和 Core 进行交互的代码。
典型的 MvvmCross 跨平台应用应当包括: 一个独立的 Core 项目包含所有的逻辑代码;每个目标平台一个 UI 项目, 包含本地化的视图以及和 Core 进行交互的代码。
Core 项目
在 Mac 系统上, 使用 Xamarin Studio 建立 Core PCL 项目, PCL项目的 Profile 选择为 158, 如下图所示:
接下来要添加对 MvvmCross 的引用, Core 项目需要引用的 dll 文件是 Cirrious.CrossCore
和 Cirrious.MvvmCross
。
MvvmCross Core 项目必须包含一个 App
类, 继承自 MvxApplication
, 负责 ViewModel 和逻辑代码的启动, 代码如下:
using FirstMvxApp.ViewModels;
using Cirrious.MvvmCross.ViewModels;
namespace FirstMvxApp {
public class App : MvxApplication {
public override void Initialize() {
base.Initialize();
RegisterAppStart<FirstViewModel>();
}
}
}
上面的代码很简单, 只是在 Initialize 方法中注册 FirstViewModel
为默认启动的 ViewModel 。
Core 项目还应该包含多个 ViewModel , 上面的 FirstViewModel
的代码如下:
using Cirrious.MvvmCross.ViewModels;
using System.Windows.Input;
namespace FirstMvxApp.ViewModels {
public class FirstViewModel : MvxViewModel {
private string firstName;
private string lastName;
private string fullName;
public string FirstName {
get {
return firstName;
}
set {
firstName = value;
RaisePropertyChanged("FirstName");
}
}
public string LastName {
get {
return lastName;
}
set {
lastName = value;
RaisePropertyChanged("LastName");
}
}
public string FullName {
get {
return fullName;
}
set {
fullName = value;
RaisePropertyChanged("FullName");
}
}
public ICommand FullNameCommand {
get {
return new MvxCommand(() => {
FullName = string.Format(
"{0} {1}",
FirstName,
LastName
);
});
}
}
}
}
最简单的 Core 项目到此就可以结束了, 只包含一个 App 和一个 FirstViewModel , 接下来就是特定平台的界面项目。
iOS 项目
新建一个 iOS 空项目, 添加对 MvvmCross 的引用, 需要的文件如下:
- Cirrious.CrossCore
- Cirrious.CrossCore.Touch
- Cirrious.MvvmCross
- Cirrious.MvvmCross.Touch
- Cirrious.MvvmCross.Binding
- Cirrious.MvvmCross.Binding.Touch
当然, 还有上面新建的 Core 项目。
添加一个 Setup
类, 负责 MvvmCross 在 iOS 应用中的启动, 代码如下:
using Cirrious.MvvmCross.Touch.Platform;
using MonoTouch.UIKit;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.CrossCore.Platform;
namespace FirstMvxApp {
public class Setup : MvxTouchSetup {
public Setup(MvxApplicationDelegate appDelegate, UIWindow window)
: base(appDelegate, window) {
}
protected override IMvxApplication CreateApp() {
return new FirstMvxApp.App();
}
protected override IMvxTrace CreateDebugTrace() {
return new DebugTrace();
}
}
}
接下来就是创建 Core 项目中 ViewModel 对应视图, Core 项目中包含 FirstViewModel
, 需要在 iOS 项目中创建对应的 FirstView
视图。 在 iOS 项目中添加 Views
目录, 然后添加一个 iPhone View Controller
, 名称为 FirstView
。 这是 MvvmCross 中默认的基于约定的命名方式, 在运行时会自动将 FirstView 的 ViewModel 设置为 FirstViewModel 。
FirstView 的界面如下图所示:
界面上控件的 outlet 名称分别为: FirstNameTextField
, LastNameTextField
, GetFullNameButton
, FullNameLabel
, 接下来的工作就是将这些界面控件与 ViewModel 的属性进行绑定, MvvmCross 实现了跨平台的数据绑定机制, 代码如下:
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.Binding.BindingContext;
using FirstMvxApp.ViewModels;
namespace FirstMvxApp.Views {
public partial class FirstView : MvxViewController {
public FirstView() : base("FirstView", null) {
}
public override void ViewDidLoad() {
base.ViewDidLoad();
this.Title = "First Mvx View";
// Perform any additional setup after loading the view, typically from a nib.
var bindings = this.CreateBindingSet<FirstView, FirstViewModel>();
bindings.Bind(FirstNameTextField).TwoWay().To(vm => vm.FirstName);
bindings.Bind(LastNameTextField).TwoWay().To(vm => vm.LastName);
bindings.Bind(GetFullNameButton).To("FullNameCommand");
bindings.Bind(FullNameLabel).To(vm => vm.FullName);
bindings.Apply();
}
}
}
绑定数据的代码非常简洁, 以后再详细介绍, 现在编译一下, 如果没有什么错误的话, 就可以直接运行了。
Android 项目
由于使用了相同的框架, 创建 Android 项目的过程和上面的 iOS 项目非常类似的, 这里只列出不同的部分。
Android 项目需要引用的文件是:
- Cirrious.CrossCore
- Cirrious.CrossCore.Droid
- Cirrious.MvvmCross
- Cirrious.MvvmCross.Droid
- Cirrious.MvvmCross.Binding
- Cirrious.MvvmCross.Binding.Droid
从引用列表可以看出, 和 iOS 项目添加的引用是等价的。
Android 版本的 Setup
和 iOS 版本相比, 除了基类不同之外, 其余完全相同, 代码如下:
using Cirrious.MvvmCross.Droid.Platform;
using Android.Content;
using Cirrious.MvvmCross.ViewModels;
using Cirrious.CrossCore.Platform;
namespace FirstMvxApp {
public class Setup : MvxAndroidSetup {
public Setup(Context applicationContext)
: base(applicationContext) {
}
protected override IMvxApplication CreateApp() {
return new App();
}
protected override IMvxTrace CreateDebugTrace() {
return new DebugTrace();
}
}
}
另外, Android 还需要一个 SplashScreen 做为启动项, 代码很简单, 如下所示:
using Android.App;
using Cirrious.MvvmCross.Droid.Views;
namespace FirstMvxApp {
[Activity(Label = "FirstMvxApp", MainLauncher = true, NoHistory = true)]
public class SplashScreen : MvxSplashScreenActivity {
public SplashScreen() : base(Resource.Layout.splash_screen) {
}
}
}
Android 的界面一般是以 xml 的形式声明的, MvvmCross 做了一些扩展, 可以再 xml 界面中直接进行数据绑定, first_view.axml 的内容如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:mvx="https://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/first_name_edit_text"
android:hint="Enter first name"
mvx:MvxBind="Text FirstName" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/last_name_edit_text"
android:hint="Enter last name"
mvx:MvxBind="Text LastName" />
<Button
android:text="Get full name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/get_full_name_button"
mvx:MvxBind="Click FullNameCommand" />
<TextView
android:textAppearance="?android:attr/textAppearanceLarge"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/full_name_text_view"
android:hint="Full name is empty."
android:gravity="center_horizontal"
mvx:MvxBind="Text FullName" />
</LinearLayout>
从上面的代码中能看到, 数据绑定全部通过 mvx:MvxBind
指令完成了, 不需要再添加数据绑定的代码。
小结
MvvmCross 给我的第一印象非常好, MVVM, DataBinding, 这些技术都是每一个 c# 开发者耳熟能详的, 而将这些技术跨平台使用是 MvvmCross 特有的, 接下来还会继续深入学习这个项目, 希望它能越来越好!
- 安装glog和gflags
- FFmpeg_3.2.4+SDL_2.0.5学习(1)音视频解码帧及显示/播放数据
- FFmpeg_3.2.4+SDL_2.0.5学习(2)视频同步基础
- ubuntu17.04更换主题
- ubuntu17.04新安装之后的软件准备
- 打造一流编辑器vimplus
- ffmpeg+sdl播放类
- 拉丁猪文字游戏
- 在Windows Mobile的控制台应用中使用Notification
- vim使用经验积累
- Spring+Mybatis+Maven+Mysql编程实战
- LD_LIBRARY_PATH和LIBRARY_PATH的区别
- c++11的Condition_variable
- lib 和 dll 的区别与使用, 没有头文件改如何使用
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel-admin 实现给grid的列添加行数序号的方法
- Laravel 自动生成验证的实例讲解:login / logout
- 关于Laravel-admin的基础用法总结和自定义model详解
- 解决Laravel5.2 Auth认证退出失效的问题
- php输出文字乱码的解决方法
- laravel-admin表单提交隐藏一些数据,回调时获取数据的方法
- laravel 5.3 单用户登录简单实现方法
- Thinkphp5.0 框架的请求方式与响应方式分析
- Yii框架视图、视图布局、视图数据块操作示例
- 用php定义一个数组最简单的方法
- laravel-admin自动生成模块,及相关基础配置方法
- laravel-admin select框默认选中的方法
- Laravel-admin之修改操作日志的方法
- php使用curl伪造浏览器访问操作示例
- 关于laravel后台模板laravel-admin select框的使用详解