0x01 前言

就目前而言,MVVM可以说是挺流行的,无论是web端还是移动端,web端的主要代表angularjs,avalonjs等,

移动端(xamarin,uwp)的代表应该是mvvmlight,mvvmcross等,

我们的主题是移动端,所以主要讲mvvmlight,mvvmcross,这篇主要讲MvvmLight,下篇讲MvvmCross。

还是以Demo的形式来谈使用。

0x02 简单的MVVM(mvvmlight) Demo

先来个web版最简单的MVVM效果,然后在按xamarin.android->uwp的顺序做一样效果的demo

注:这个效果是基于 avalonjs的

下面来看看我们的第一个例子(Xamarin.Android):

新建一个Android项目Catcher.MVVMDemo.Day01DroidByMvvmLight

通过NuGet安装相关组件(MvvmLight)。

然后编写我们的Main.axml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/et_input" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/tv_input" />
</LinearLayout>

然后去修改MainActivity

 using Android.App;
using Android.OS;
using Android.Widget;
using GalaSoft.MvvmLight.Helpers;
using GalaSoft.MvvmLight.Views;
namespace Catcher.MVVMDemo.Day01DroidByMvvmLight
{
[Activity(Label = "MvvmLightDemo", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : ActivityBase
{
EditText etInput;
TextView tvInput;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
etInput = FindViewById<EditText>(Resource.Id.et_input);
tvInput = FindViewById<TextView>(Resource.Id.tv_input); this.SetBinding(() => etInput.Text, () => tvInput.Text);
}
}
}

MainActivity是继承ActivityBase,同时将输入的值绑定在TextView上。

效果图如下:

第二个例子(UWP):

新建一个Universal Windows项目:Catcher.MVVMDemo.Day01UWP

修改我们的MainPage.xaml

 <Page
x:Class="Catcher.MVVMDemo.Day01UWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Catcher.MVVMDemo.Day01UWP"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<StackPanel VerticalAlignment="Top">
<TextBox x:Name="txtName"/>
<TextBlock Text="{Binding ElementName=txtName,Path=Text}"/>
</StackPanel>
</Grid>
</Page>

这里直接在页面通过Binding来绑定了。相比Android简洁了不少。

效果如下:

到这里,这两个简单的例子已经OK了,你是不是也想动手试试呢!

不过这两个例子并没有涉及到Mvvm主要的东西。至少连ViewModel的影子都还没出现呢。

0x03 MVVM(mvvmlight) 登陆Demo

开始之前,我们新建一个类库项目Catcher.MVVMDemo.Day01Core

这个类库是后面的2个例子都要用到的,处理我们的ViewModel。

通过NuGet安装MvvmLight

在ViewModel文件夹下面添加一个LoginViewModel

 using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using GalaSoft.MvvmLight.Views;
using Microsoft.Practices.ServiceLocation;
using System.Diagnostics;
namespace Catcher.MVVMDemo.Day01Core.ViewModel
{
public class LoginViewModel : ViewModelBase
{
public LoginViewModel()
{
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
//RaisePropertyChanged("Name");
RaisePropertyChanged(() => Name);
}
}
private string _password;
public string Password
{
get
{
return _password;
}
set
{
_password = value;
RaisePropertyChanged(() => Password);
}
}
/// <summary>
/// login command
/// </summary>
public RelayCommand LoginCommand
{
get
{
return new RelayCommand(() => Login());
}
}
/// <summary>
/// login
/// </summary>
private void Login()
{
//Valid the user
if (Name == "catcher" && Password == "")
{
var nav = ServiceLocator.Current.GetInstance<INavigationService>();
nav.NavigateTo("Main");
}
else
{
var dialog = ServiceLocator.Current.GetInstance<IDialogService>();
dialog.ShowMessage(
"check your name and password",
"infomation",
"OK",
null);
}
}
}
}

这里的登陆是写死了一个用户名和密码。

同时,修改我们的ViewModelLocator,添加我们LoginViewModel的信息

 using GalaSoft.MvvmLight.Ioc;
using Microsoft.Practices.ServiceLocation;
namespace Catcher.MVVMDemo.Day01Core.ViewModel
{
public class ViewModelLocator
{
public ViewModelLocator()
{
//provider
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
//view model
SimpleIoc.Default.Register<MainViewModel>();
SimpleIoc.Default.Register<LoginViewModel>();
}
public MainViewModel Main
{
get
{
return ServiceLocator.Current.GetInstance<MainViewModel>();
}
}
public LoginViewModel LoginViewModel
{
get
{
return ServiceLocator.Current.GetInstance<LoginViewModel>();
}
}
public static void Cleanup()
{
}
}
}

到这里,我们将ViewModel的相关处理做好了。

下面两个例子就是添加一个登陆页面,提供验证,登陆成功就跳转到我们前面两个例子的页面,不成功就弹框提示。

第三个例子(Xamarin.Android):

在刚才的Catcher.MVVMDemo.Day01DroidByMvvmLight中,添加一个App.cs,主要是注册一些东西

 using Catcher.MVVMDemo.Day01Core.ViewModel;
using GalaSoft.MvvmLight.Views;
using GalaSoft.MvvmLight.Ioc;
namespace Catcher.MVVMDemo.Day01DroidByMvvmLight
{
public static class App
{
private static ViewModelLocator _locator;
public static ViewModelLocator Locator
{
get
{
if (_locator == null)
{
var nav = new NavigationService();
nav.Configure("Main", typeof(MainActivity)); SimpleIoc.Default.Register<INavigationService>(() => nav);
//the dialog
SimpleIoc.Default.Register<IDialogService, DialogService>();
_locator = new ViewModelLocator();
}
return _locator;
}
}
}
}

添加一个login.axml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="enter your name"
android:id="@+id/et_name" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:hint="enter your password"
android:id="@+id/et_pwd" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Login"
android:id="@+id/btn_login" />
</LinearLayout>

添加一个LoginActivity,与LoginViewModel相适配。

 using Android.App;
using Android.OS;
using Android.Widget;
using Catcher.MVVMDemo.Day01Core.ViewModel;
using GalaSoft.MvvmLight.Helpers;
using GalaSoft.MvvmLight.Views;
namespace Catcher.MVVMDemo.Day01DroidByMvvmLight
{
[Activity(Label = "Login", MainLauncher = true, Icon = "@drawable/icon")]
public class LoginActivity : ActivityBase
{
/// <summary>
/// the view model
/// </summary>
public LoginViewModel VM
{
get { return App.Locator.LoginViewModel; }
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.login);
EditText etName = FindViewById<EditText>(Resource.Id.et_name);
EditText etPassword = FindViewById<EditText>(Resource.Id.et_pwd);
Button btnLogin = FindViewById<Button>(Resource.Id.btn_login);
//binding
this.SetBinding(() => VM.Name, etName, () => etName.Text, BindingMode.TwoWay);
this.SetBinding(() => VM.Password, etPassword, () => etPassword.Text, BindingMode.TwoWay);
//button click
btnLogin.SetCommand("Click", VM.LoginCommand);
}
}
}

VM通过App.cs里面的来获取。

两个输入框的绑定方式设为TwoWay。

按钮的点击事件设为LoginViewModel的LoginCommand。

最后去掉MainActivity的MainLauncher=true

效果图如下:

第四个例子(UWP):

在刚才的Catcher.MVVMDemo.Day01UWP中,添加一个LoginPage.xaml

 <Page
x:Class="Catcher.MVVMDemo.Day01UWP.LoginPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Catcher.MVVMDemo.Day01UWP"
xmlns:vm="using:Catcher.MVVMDemo.Day01Core.ViewModel"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.DataContext>
<vm:LoginViewModel />
</Page.DataContext>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="5*"></RowDefinition>
</Grid.RowDefinitions>
<TextBox Grid.Row="1" Margin="15" Height="20" Text="{Binding Name,Mode=TwoWay}" PlaceholderText="enter you name" />
<PasswordBox Grid.Row="2" Margin="15" Height="20" Password="{Binding Password,Mode=TwoWay}" PasswordChar="*" PlaceholderText="enter your password" />
<Button Grid.Row="3" Margin="15,10" Content="Login" Command="{Binding LoginCommand}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
</Page>

通过Page.DataContext设置了ViewModel

对TextBox,PasswordBox和button进行了相应的绑定。

然后修改App.xaml.cs中的OnLaunched方法,主要是启动页面和注册MvvmLight的东西

        protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached)
{
this.DebugSettings.EnableFrameRateCounter = true;
}
#endif
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
rootFrame = new Frame();
rootFrame.NavigationFailed += OnNavigationFailed;
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
} Window.Current.Content = rootFrame;
}
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(LoginPage), e.Arguments);
} Window.Current.Activate();
//
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
var navigationService = new NavigationService();
navigationService.Configure("Login", typeof(LoginPage));
navigationService.Configure("Main", typeof(MainPage));
SimpleIoc.Default.Register<INavigationService>(() => navigationService);
SimpleIoc.Default.Register<IDialogService, DialogService>();
}
}

效果图:

0x04 简单总结

对于Android来说,主要以下几个点:

1.Activity是继承了MvvmLight自己实现的ActivityBase,具体如下:

 namespace GalaSoft.MvvmLight.Views
{
public class ActivityBase : Activity
{
public ActivityBase();
public static ActivityBase CurrentActivity { get; }
public static void GoBack();
protected override void OnResume();
}
}

2.ViewModel继承ViewModelBase这个抽象类,在深究必然离不开INotifyPropertyChanged这个接口。

    public abstract class ViewModelBase : ObservableObject, ICleanup

     public class ObservableObject : INotifyPropertyChanged

3.在ViewModelLocator里面通过SimpleIoc注册我们的ViewModel,当然也可以用Autofac等。

4.SetBinding和SetCommand的应用,可以看看具体的实现

对UWP来说,除了公共部分,与Android的区别就是在xaml中绑定了属性和“事件”。

下一篇会讲讲MvvmCross的简单使用。

Xamarin.Android和UWP之MVVM的简单使用(一)的更多相关文章

  1. Xamarin.Android和UWP之MVVM的简单使用(二)

    0x01 前言 前面一篇,Xamarin.Android和UWP之MVVM的简单使用(一),主要讲了MvvmLight的简单使用 这篇主要讲讲MvvmCross的简单使用,例子的话,还是和上篇的一样. ...

  2. Xamarin.Android之Splash的几种简单实现

    对现在的APP软件来说,基本上都会有一个Splash页面,类似大家常说的欢迎页面.启动界面之类的. 正常来说这个页面都会有一些相关的信息,比如一些理念,Logo,版本信息等 下面就来看看在Xamari ...

  3. Xamarin android spinner的使用方法

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  4. Xamarin Android 中Acitvity如何传递数据

    在xamarin android的开发中,activity传递数据非常常见,下面我也来记一下在android中activity之间传递数据的几种方式, Xamarin Android中Activity ...

  5. MVP架构在xamarin android中的简单使用

    好几个月没写文章了,使用xamarin android也快接近两年,还有一个月职业生涯就到两个年了,从刚出来啥也不会了,到现在回头看这个项目,真jb操蛋(真辛苦了实施的人了,无数次吐槽怎么这么丑),怪 ...

  6. Xamarin.Android之引导页的简单制作

    0x01 前言 对于现在大部分的APP,第一次打开刚安装或更新安装的APP都会有几个引导界面,通常这几个引导页是告诉用户 APP有些什么功能或者修改了什么bug.新增了什么功能等等等. 下面就用Xam ...

  7. Xamarin.Android之简单的抽屉布局

    0x01 前言 相信对于用过Android版QQ的,应该都不会陌生它那个向右滑动的菜单(虽说我用的是Lumia) 今天就用Xamarin.Android实现个比较简单的抽屉布局.下面直接进正题. 0x ...

  8. Xamarin.Android之封装个简单的网络请求类

    一.前言 回忆到上篇 <Xamarin.Android再体验之简单的登录Demo> 做登录时,用的是GET的请求,还用的是同步, 于是现在将其简单的改写,做了个简单的封装,包含基于Http ...

  9. 基于Xamarin Android实现的简单的浏览器

    最近做了一个Android浏览器,当然功能比较简单,主要实现了自己想要的一些功能……现在有好多浏览器为什么还要自己写?当你使用的时候总有那么一些地方不如意,于是就想自己写一个. 开发环境:Xamari ...

随机推荐

  1. 系统吞吐量(TPS)、用户并发量、性能测试概念和公式

    分享一个概念: http://www.ha97.com/5095.html

  2. 通过html和css做出下拉导航栏的效果

    通过观察了百度的首页,对于更多产品一栏,觉得可以不涉及JS便可写出下拉导航栏的效果 1.先设计出大体的框架 <div class="nav"> <ul> & ...

  3. 一个哥们看到数据库日志不断增大 [log_reuse_wait_desc]为replication 之后的做法

    一哥们看到数据库日志不断增大 [log_reuse_wait_desc]为replication 之后的做法 一天那个哥们看到数据库日志暴涨,用sys.databases 视图看一下[log_reus ...

  4. 将asp.net core站点发布到IIS上遇到的问题

    今天第一次将整个 asp.net core 站点发布到 IIS 上,以前都是发布到 Linux 服务器上. 开始使用 dotnet publish -c release 命令发布,用浏览器访问站点时出 ...

  5. Step by step 活动目录中添加一个子域

    原创地址:http://www.cnblogs.com/jfzhu/p/4006545.html 转载请注明出处 前面介绍过如何创建一个域,下面再介绍一下如何在该父域中添加一个子域. 活动目录中的森林 ...

  6. 在互联网公司参与拍卖是一种怎样的感觉?part 1

    拍卖在中国是不太流行的一件事,为什么呢?说不太出.当初在外国火的不得了的ebay在交易时采用的就是拍卖出价的模式,但进入中国后这种方式就是玩不转,不得以后来也变成了跟淘宝一样的一口价方式. 话说现在每 ...

  7. eclipse下打包实践

    前提: 配置好打包相关的插件,看打包的结果分别添加不同的plugin,装好m2eclipse. 以下步骤以war包的packing为例. 步骤: 如下图:右键,选择Run As 或者 Debug As ...

  8. Drupal8重命名上传的中文名文件

    完整的模块代码文件在Coding.net上,想直接使用的请前往下载:https://coding.net/u/yamus/p/chinese_rename/git/tree/master 最近吧Dru ...

  9. 考勤系统代码分析——主页布局easyui框架

    考勤系统主页的布局用的是easyui的Layout控件 Layout:布局容器有5个区域:北.南.东.西和中间.中间区域面板是必须的,边缘的面板都是可选的.每个边缘区域面板都可以通过拖拽其边框改变大小 ...

  10. UpdateData(TRUE)与UpdateData(FALSE)的使用

    二者是更新对话框的控件与变量. 1.先要建立对应关系 如 编辑框IDC_Edit  和 变量 m_name DDX_Text(pDX, IDC_EDIT, m_name); 2.若是在编辑框输入名字 ...