前言

系列目录

C#使用Xamarin开发可移植移动应用目录

源码地址:https://github.com/l2999019/DemoApp

可以Star一下,随意 - -

说点什么..

嗯..前面3篇就是基础内容..后面就开始逐渐要加深了,进阶篇开始了.

今天的学习内容?

今天我们讲讲Xamarin中的MVVM双向绑定,嗯..需要有一定的MVVM基础.,具体什么是MVVM - -,请百度,我就不多讲了

效果如下:

正文

1.简单的入门Demo

这个时间的功能很简单,就是一个时间的动态显示.

我们首先创建一个基础的页面如下:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DemoApp.MVVMDemo.ViewModel"
x:Class="DemoApp.MVVMDemo.MVVMPageDemo">
<ContentPage.Content> <StackLayout >
<Label Text="{Binding DateTime,StringFormat='{0:F}'}">
<Label.BindingContext>
<local:TimeViewModel></local:TimeViewModel>
</Label.BindingContext>
</Label> </StackLayout>
</ContentPage.Content>
</ContentPage>

大家可以发现,我们这次多了一些内容.

首先,我们会发现ContentPage的xmlns定义中多了一个local的定义.这个很重要,他是用来让我们在xaml中引用其他程序集中的类,类似于Using的作用.

剩下的BindingContext和Bingding关键字,后面我们慢慢讲

接下来,我们创建一个ViewModel的类如下:

  public class TimeViewModel : INotifyPropertyChanged
{
//定义一个时间类型
DateTime dateTime; //实现接口的事件属性
public event PropertyChangedEventHandler PropertyChanged; //创建构造函数,定义一个定时执行程序
public TimeViewModel()
{
this.DateTime = DateTime.Now; //定义定时执行程序,1秒刷新一下时间属性
Device.StartTimer(TimeSpan.FromSeconds(), () =>
{
this.DateTime = DateTime.Now;
return true;
});
} //定义时间属性,创建SetGet方法,在Set中使用PropertyChanged事件,来更新这个时间
public DateTime DateTime
{
set
{
if (dateTime != value)
{
dateTime = value; if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs("DateTime"));
}
}
}
get
{
return dateTime;
}
}
}

我们继承了INotifyPropertyChanged,从类名就可以看出来,这个是关于实现属性变更事件的一个接口.

他包含一个PropertyChanged,属性变更事件,我们需要在每个属性变更的时候(也就是Set中),调用它

在具体的开发过程中,如果你需要使用MVVM那么你所有的ViewModel都应该继承它.

很多解释我都写在了注释里面,请仔细看注释

然后我们回到Xaml中的BindingContext,它的作用就一目了然了,给这个Xaml控件,绑定一个上下文对象,也就是你定义的ViewModel,来方便你绑定其中的属性

<Label Text="{Binding DateTime,StringFormat='{0:F}'}"> 这句的意思就是,绑定其中的DateTime属性,并格式化显示.

我们在构造函数中启动的定时程序,就会一直更新DateTime,对应的,页面上也会一直随着变更.这样我们就实现了一个基础的MVVM

效果如图:

2.学会与控件相联系,并绑定命令事件

通过上面的小栗子,我们学习了一下基本的绑定关系和绑定方法.

那么下面就来一个比较复杂,比较难的例子.效果是这样的,如图:

我们创建三个数值,他们与控件Slider来绑定,并控制.更新值的同时,求和.得到NumSun的值.

在界面中,我们有一个清空的Button来清除这个ViewModel中的值.

首先,我们创建xaml代码如下:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DemoApp.MVVMDemo.ViewModel"
x:Class="DemoApp.MVVMDemo.MVVMDemoPage2">
<ContentPage.BindingContext>
<local:AddNumViewModel></local:AddNumViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout>
<Label Text="{Binding NumSun,Mode=TwoWay,StringFormat='总数NumSun={0:F2}'}" />
<Label Text="{Binding Num1,
StringFormat='Num1 = {0:F2}'}" />
<Slider Value="{Binding Num1,Mode=TwoWay}" />
<Label Text="{Binding Num2,
StringFormat='Num2 = {0:F2}'}" />
<Slider Value="{Binding Num2,Mode=TwoWay}" />
<Label Text="{Binding Num3,
StringFormat='Num3 = {0:F2}'}" />
<Slider Value="{Binding Num3,Mode=TwoWay}" />
<Button Text="清空" Command="{Binding CleanCommand}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>

然后创建我们的ViewModel代码如下:

    public class AddNumViewModel : INotifyPropertyChanged
{
//定义属性值
double num1, num2, num3,numSun;
public event PropertyChangedEventHandler PropertyChanged;
//定义清空的命令
public ICommand CleanCommand { protected set; get; } public AddNumViewModel()
{
//实现清空
this.CleanCommand = new Command((key) =>
{
this.NumSun = ;
this.Num1 = ;
this.Num2 = ;
this.Num3 = ;
}); } /// <summary>
/// 统一的属性变更事件判断方法
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
} public double Num1
{
set
{
if (num1 != value)
{
num1 = value;
OnPropertyChanged("Num1");
SetNewSunNum();
}
}
get
{
return num1;
}
} public double Num2
{
set
{
if (num2 != value)
{
num2 = value;
OnPropertyChanged("Num2");
SetNewSunNum();
}
}
get
{
return num2;
}
} public double Num3
{
set
{
if (num3 != value)
{
num3 = value;
OnPropertyChanged("Num3");
SetNewSunNum();
}
}
get
{
return num3;
}
} public double NumSun
{
set
{
if (numSun != value)
{
numSun = value;
OnPropertyChanged("NumSun"); }
}
get
{
return numSun;
}
} /// <summary>
/// 把数值加起来的方法(业务逻辑)
/// </summary>
void SetNewSunNum()
{
this.NumSun = this.Num1 + this.Num2 + this.Num3;
} }

很简单,我们创建了Num1,Num2,Num3和NumSun四个属性.实现了一个SetNewSunNum的方法,来求和.

然后就一一对应的在xaml中绑定了相关的属性.所有的Slider绑定中都有个Mode=TwoWay,意思就是,这个属性为双向绑定,在控件中变更它的同时,也会在ViewModel中变更.

然后我们在来看看清空按钮的命令绑定.

先解释一下,为什么会有命令绑定这个东西,因为我们使用双向绑定的时候,页面的点击事件,并不能直接调用到ViewModel,所以就衍生了一个叫命令绑定的东西.来和我们控件的各种事件相关联.

我们回到代码,会发现,在AddNumViewModel中,我们定义了一个继承自 ICommandCleanCommand 的命令,并在构造函数中实现了它

在我们的xaml中,buttom绑定了这个事件 <Button Text="清空" Command="{Binding CleanCommand}" />

这样,就可以直接调用到ViewModel了,当然你的命令也可以传递参数,如下:

<Button Text="清空" Command="{Binding CleanCommand}" CommandParameter="aaa" />

aaa就是你传递的参数.

接收也很简单,稍微改一下.CleanCommand 如下:

这个key就是你传递进来的参数了..

3.回顾一下.

今天主要学习了Xamarin中的MVVM双向绑定和命令绑定,

需要双向绑定的类,需要继承INotifyPropertyChanged,需要绑定的命令,需要继承:ICommand

最后,列一下可以使用命令绑定的控件.

  • Button

  • MenuItem

  • ToolbarItem

  • SearchBar

  • TextCell(所以也包含ImageCell

  • ListView

  • TapGestureRecognizer

除了SearchBar和 ListView这两个控件之外,这些控件都可以使用Command 和CommandParameter

嗯..,SearchBar定义SearchCommandSearchCommandParameter属性,而ListView定义一个RefreshCommand属性的类型ICommand

其实都是一样的..名字换了一下..

 

 
写在最后

嗯..没啥好说的..持续更新中..

C#使用Xamarin开发可移植移动应用(4.进阶篇MVVM双向绑定和命令绑定)附源码的更多相关文章

  1. C#使用Xamarin开发可移植移动应用(3.进阶篇MVVM双向绑定和命令绑定)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 嗯..前面 ...

  2. C#使用Xamarin开发可移植移动应用(5.进阶篇显示弹出窗口与通讯中心)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 没啥好说的 ...

  3. 仿酷狗音乐播放器开发日志二十七 用ole为窗体增加文件拖动功能(附源码)

    转载请说明原出处,谢谢~~ 中秋到了,出去玩了几天.今天把仿酷狗程序做了收尾,已经开发完成了,下一篇博客把完结的情况说一下.在这篇博客里说一下使用OLE为窗体增加文件拖拽的功能.使用播放器,我更喜欢直 ...

  4. C#使用Xamarin开发可移植移动应用(1.入门与Xamarin.Forms页面),附源码

    前言 什么是Xamarin? Xamarin始创于2011年,旨在使移动开发变得难以置信地迅捷和简单. Xamarin的产品简化了针对多种平台的应用开发,包括iOS.Android.Windows P ...

  5. C#使用Xamarin开发可移植移动应用(2.Xamarin.Forms布局,本篇很长,注意)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 一点感想 很意外的,第一 ...

  6. C#使用Xamarin开发可移植移动应用目录

    Xamarin.Android系列 C#开发移动应用系列(1.环境搭建) C#开发移动应用系列(2.使用WebView搭建WebApp应用) C#开发移动应用系列(3.使用照相机扫描二维码+各种基础知 ...

  7. C#使用Xamarin开发可移植移动应用(3.Xamarin.Views控件)附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. .NET ...

  8. C#使用Xamarin开发可移植移动应用进阶篇(6.使用渲染器针对单个平台自定义控件..很很很很重要..),附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 本篇..基 ...

  9. C#使用Xamarin开发可移植移动应用进阶篇(7.使用布局渲染器,修改默认布局),附源码

    前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 本篇..基 ...

随机推荐

  1. Java 读书笔记 (四) 常量

    常量在程序运行时不能被修改. 在Java中使用final 关键字来修饰常量 ,声明方式和变量类似: final double PI=3.1415927 常量名也可以用小写,但为了便于识别,通常使用大写 ...

  2. java的classpath路径中加点号 ‘.’ 的作用

    "."表示当前目录,就是编译或者执行程序时你所在的目录下的.class文件:而JAvA_HOME表示JDK安装路径 该路径在eclipse中是以vmarg的形式传入的,可以在任务管 ...

  3. layer的删除询问框的使用

    删除是个很需要谨慎的操作 我们需要进行确认 对了删除一般使用ajax操作 因为如果同url请求 处理 再返回 会有空白页 1.js自带的样式 <button type="button& ...

  4. 【源码安装】Heartbeat3.0.9

    1.概述1.1 关于Heartbeat1.2 本篇博客实践环境2. 部署基础环境2.1 通过YUM安装依赖环境2.2 创建Heartbeat用户和组3. 编译安装3.1下载源码包3.2 编译安装3.2 ...

  5. Linux文件系统选择

    通过综合使用多种标准文件系统Benchmarks对Ext3, Ext4, Reiserfs, XFS, JFS, Reiser4的性能测试对比,对不同应用选择合适的文件系统给出以下方案,供大家参考.文 ...

  6. Leetcode解题思路总结(Easy篇)

    终于刷完了leetcode的前250道题的easy篇.好吧,其实也就60多道题,但是其中的套路还是值得被记录的. 至于全部code,请移步github,题目大部分采用python3,小部分使用C,如有 ...

  7. 使用NOOBS给树莓派安装系统Raspbian

    使用NOOBS给树莓派安装系统Raspbian --英文原版教程:https://www.raspberrypi.org/learning/software-guide/quickstart/ 1.原 ...

  8. React Native开发 - 搭建React Native开发环境

    移动开发以前一般都是原生的语言来开发,Android开发是用Java语言,IOS的开发是Object-C或者Swift.那么对于开发一个App,至少需要两套代码.两个团队.对于公司来说,成本还是有的. ...

  9. 小白学习Python之路---re模块学习和挑战练习

    本节大纲: 1.正则表达式 2.re模块的学习 3.速记理解技巧 4.挑战练习--开发一个简单的python计算器 5.心得总结 6.学习建议 正则表达式: 正则表达式,又称规则表达式.(英语:Reg ...

  10. 【JVM虚拟机】(5)---深入理解JVM-Class中常量池

    深入理解Class---常量池 一.概念 1.jvm生命周期 启动:当启动一个java程序时,一个jvm实例就诞生了,任何一个拥有main方法的class都可以作为jvm实例运行的起点. 运行:mai ...