Xamarin + MvvmCross 简单事例 Part 2
MvvmCross
说起MvvmCross,要先说到Mvvm,Mvvm是Mvc框架的一种变形。对应的分别为Model、View和ViewModel层。三层之间的关系是这样的:
Model层为数据层,实现了业务数据的定义,View层为表现层,ViewModel层隔离了数据层和表现层,实现了对业务数据的隔离以及和表现层数据的绑定。
创建解决方案
1. 先要创建一个Xamarin跨平台的解决方案。方案模板使用Blank Xaml App(Xamarin.Forms Protable)。
2. 创建好的解决方案大体应该是这样子,包含一个可移植的项目、一个Android的项目和一个iOS的项目。如果有其它的项目,我们暂时移除掉。
3. 添加MvvmCross引用。引用MvvmCross需要从Nuget中添加。
在解决方案上点击右键,选择 管理解决方案NuGet程序包 这一项。
4. 在NuGet管理器中直接搜索 MvvmCross,搜索结果第一项就是MvvmCross
在右边的解决方案栏中选择要引用MvvmCross的项目,点击安装,Nuget管理器自动下载MvvmCross并添加引用。
安装完成后,查看解决方案,我们会发现项目已经引用了MvvmCross相应的程序集。
可移植项目
可移植项目做为解决方案共享的项目,主要建立所有项目公用的内容。这里我们主要建立公共类库以及ViewModel。
1. 首先将项目中的App.xaml和mainPage.xaml移除。
2. 新建一个ViewModels文件夹,保存公共的ViewModel。
3. 在ViewModels下新建MainViewModel.cs。
4. 新建App类,做为MvvmCross公共的应用程序入口。
整理后项目结构大体是这样的
- App.cs
using Acr.UserDialogs; using MvvmCross.Core.ViewModels; using MvvmCross.Platform; using MvvmCross.Platform.IoC; using XamarinSample.ViewModels; namespace XamarinSample { public class App : MvxApplication { public override void Initialize() { base.Initialize(); // 注册所有的服务类 CreatableTypes().EndingWith("Service").AsInterfaces().RegisterAsLazySingleton(); Mvx.RegisterSingleton(UserDialogs.Instance); RegisterAppStart<MainViewModel>(); } } }
- MainViewModel.cs
using System.Windows.Input; using MvvmCross.Core.ViewModels; namespace XamarinSample.ViewModels { public class MainViewModel : MvxViewModel { /// <summary> /// 获取或设置标题 /// 设置标题时将触发属性改变事件 /// </summary> public string Title { get { return _title; } set { _title = value; RaisePropertyChanged(() => _title); } } private ICommand _showTitleCommand; private string _title; /// <summary> /// 获取 显示标题的Command /// </summary> public ICommand ShowTitleCommand { get { return _showTitleCommand ?? (_showTitleCommand = new MvxCommand(ShowTitle)); } } private void ShowTitle() { Acr.UserDialogs.UserDialogs.Instance.Alert(Title,"这是一个标题", "知道了"); } } }
通过以上步骤,可移植项目已经整理完成了,下面我们针对各个移动端项目分别实现调用。
Android项目
Android项目主要实现Android界面以及界面逻辑。我们分别创建界面布局、与ViewModel绑定以及实现界面逻辑。
1. 添加MvvmCross 在Android项目的Setup类。
2. 添加界面布局并绑定ViewModel数据。
3. 实现入口Activity,绑定布局。
- Setup.cs
using Android.Content; using MvvmCross.Core.ViewModels; using MvvmCross.Droid.Platform; namespace XamarinSample.Droid { public class Setup : MvxAndroidSetup { public Setup(Context applicationContext) : base(applicationContext) { } protected override IMvxApplication CreateApp() { return new App(); } } }
- MainPage.axml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:local="http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="50" android:id="@+id/textView2" android:singleLine="true" android:gravity="center_vertical" local:MvxBind="Text Title, Mode=TwoWay" android:hint="请输入标题" android:inputType="text" android:layout_marginTop="100" android:layout_marginBottom="20" android:textSize="26dip" android:background="@color/design_fab_stroke_end_outer_color" /> <Button android:text="显示标题" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/button1" local:MvxBind="Click ShowTitleCommand" android:textSize="30dip" /> </LinearLayout>
- MainActivity.cs
using Android.App; using Android.Content.PM; using Android.OS; using MvvmCross.Droid.Views; using XamarinSample.ViewModels; namespace XamarinSample.Droid { [Activity(Label = "XamarinSample", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)] public class MainActivity : MvxActivity<MainViewModel> { protected override void OnCreate(Bundle bundle) { base.OnCreate(bundle); SetContentView(Resource.Layout.MainPage); } } }
OK, 至此Android端的项目完成了,让我们执行一下看看效果
iOS项目
iOS 项目也主要实现了iOS上的界面逻辑,但如果要完成iOS的界面设计,需要连接到Mac系统才能在VS中进行界面设计。
- 添加iOS项目的Setup对象。
Setup.cs
using MvvmCross.Core.ViewModels; using MvvmCross.iOS.Platform; using MvvmCross.iOS.Views.Presenters; using UIKit; namespace XamarinSample.iOS { public class Setup : MvxIosSetup { protected override IMvxApplication CreateApp() { return new App(); } public Setup(IMvxApplicationDelegate applicationDelegate, UIWindow window) : base(applicationDelegate, window) { } public Setup(IMvxApplicationDelegate applicationDelegate, IMvxIosViewPresenter presenter) : base(applicationDelegate, presenter) { } } }
- 在修改 AppDelegate.cs 文件,对象继承于 ,修改FindishedLaunching方法。
using Foundation; using MvvmCross.Core.ViewModels; using MvvmCross.iOS.Platform; using MvvmCross.Platform; using UIKit; namespace XamarinSample.iOS { [Register("AppDelegate")] public class AppDelegate : MvxApplicationDelegate { public override UIWindow Window { get; set; } public override bool FinishedLaunching(UIApplication app, NSDictionary options) { Window = new UIWindow(UIScreen.MainScreen.Bounds); var setup = new Setup(this, Window); setup.Initialize(); var startup = Mvx.Resolve<IMvxAppStart>(); startup.Start(); Window.MakeKeyAndVisible(); return true; } } }
- 新建Views文件夹,并在文件夹下添加界面文件MainView。
- 打开MainView.xib界面文件,进行界面设计。
我们在界面上添加一个TextField和一个Button,分别命名为txtField和btnShow。
- 修改MainView.cs对象,实现数据绑定。
using MvvmCross.Binding.BindingContext; using MvvmCross.iOS.Views; using UIKit; using XamarinSample.ViewModels; namespace XamarinSample.iOS.Views { public partial class MainView : MvxViewController<MainViewModel> { public MainView() : base("MainView", null) { } public override void DidReceiveMemoryWarning() { base.DidReceiveMemoryWarning(); // Release any cached data, images, etc that aren‘t in use. } public override void ViewDidLoad() { base.ViewDidLoad(); var set = this.CreateBindingSet<MainView, MainViewModel>(); set.Bind(txtTitle).To(vm => vm.Title); set.Bind(btnShow).To(x => x.ShowTitleCommand); set.Apply(); // Perform any additional setup after loading the view, typically from a nib. } } }
好了,iOS的项目也设计完成了,我们运行一下看看效果。