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

今天的学习内容?

今天我们讲讲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(1), () =>

            {

                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 = 0;

                this.Num1 = 0;

                this.Num2 = 0;

                this.Num3 = 0;

            });


        }


        /// <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开发可移植移动应用(1.入门与Xamarin.Forms页面),附源码

  • .NET Standard@Xamarin.Forms

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

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

原文地址:http://www.cnblogs.com/GuZhenYin/p/7381973.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324109.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

由「Metaspace容量不足触发CMS GC」从而引发的思考

转载自 由「Metaspace容量不足触发CMS GC」从而引发的思考 某天早上&#xff0c;毛老师在群里问「cat 上怎么看 gc」。 好好的一个群 看到有 GC 的问题&#xff0c;立马做出小鸡搓手状。 之后毛老师发来一张图。 老年代内存占用情况 图片展示了老年代内存占用情况。 第一个…

P1040,jzoj1167-加分二叉树【树形dp】

前言 没有SPJ坑了我好久qwq 正题 测试连接&#xff1a;https://www.luogu.org/recordnew/lists?uid52918&pidP1040 大意 一颗二叉树的中序遍历是1,2,3...n−2,n−1,n1,2,3...n−2,n−1,n然后给出每个点的值aiai&#xff0c;每个点的分数是 sislsonsrsonaisislsonsrsona…

是现在的钱不值钱还是药太贵!

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号【雄雄的小课堂】。莫名其妙的就感觉身体不舒服&#xff0c;然后越来越严重&#xff0c;打小以来还是第一次遇见这样的&#xff0c;你说是感冒吧&#xff0c;它也不流鼻涕&#xff0c;喉咙也不痛&#xff0c;鼻子也通…

P3951,jzoj5473-小凯的疑惑【数论】(NOIP2017提高组)

#正题 评测记录&#xff1a; https://www.luogu.org/recordnew/show/8283818 大意 两个币值&#xff08;互质正整数&#xff09;&#xff0c;求不能完全&#xff08;需要找零&#xff09;的最贵的东西。 解题思路 首先众所周知axbyc而且a和b互质的正整数&#xff0c;c为正整数…

一次堆外内存泄露的排查过程

转载自 一次堆外内存泄露的排查过程 最近在做一个基于 websocket 的长连中间件&#xff0c;服务端使用实现了 socket.io 协议&#xff08;基于websocket协议&#xff0c;提供长轮询降级能力&#xff09; 的 netty-socketio 框架&#xff0c;该框架为 netty 实现&#xff0c;鉴…

.NET Core 2.0 特性介绍和使用指南

前言 这一篇会比较长&#xff0c;介绍了.NET Core 2.0新特性、工具支持及系统生态&#xff0c;现状及未来计划&#xff0c;可以作为一门技术的概述来读&#xff0c;也可以作为学习路径、提纲来用。 对于.NET Core 2.0的发布介绍&#xff0c;围绕2.0的架构体系&#xff0c;我想…

Lombok MyBatisX

Lombok的使用 [1] 什么是LomBok lombok是一个可以通过简单的注解的形式来帮助我们简化消除一些必须有但显得很臃肿的 Java 代码的工具&#xff0c;简单来说&#xff0c;比如我们新建了一个类&#xff0c;然后在其中写了几个属性&#xff0c;然后通常情况下我们需要手动去建立g…

希望尽快好起来吧~

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。莫名其妙的生病&#xff0c;每天睡觉之前都在祷告&#xff0c;睡一觉明天早上就好了&#xff0c;结果第二天非但没有好&#xff0c;反而还加重了。买的药吃了也无济于事&#xff0c;还渐渐的开始发烧……

2018/7/9-纪中某B组题【jzoj1503,jzoj1158,jzoj1161】

正题 T1&#xff1a;jzoj1503-体育场【带权并查集】 博客链接&#xff1a;https://blog.csdn.net/mr_wuyongcong/article/details/80969720 T2&#xff1a;jzoj1158-荒岛野人【扩欧,gcd,同余方程】 博客链接&#xff1a;https://blog.csdn.net/mr_wuyongcong/article/details…

一次堆外OOM问题的排查过程

转载自 一次堆外OOM问题的排查过程 背景 线上服务有一台机器访问不通&#xff08;一个管理平台),在公司的服务治理平台上查看服务的状况是正常的&#xff0c;说明进程还在。进程并没有完全crash掉。去线上查看机器日志&#xff0c;发现了大量的OOM异常: 017-03-15 00:00:0…

Azure与Scott Guthrie:Azure安全中心和基于角色的访问控制

InfoQ有幸采访了Microsoft执行副总裁Scott Guthrie&#xff0c;请他谈了谈Azure以及他最近的Red Shirt Dev Tours&#xff08;红杉开发之旅&#xff09;【译注1】。昨天我们谈到了Azure提供了自定义仪表盘的功能&#xff0c;它能够使得开发者创建自定义工作任务流程&#xff0c…

什么时候才能都及格呢?

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。今天是周五&#xff0c;又到了周测的时候了&#xff0c;发现现在考试&#xff0c;学生们的抵触情绪不会那么强烈了&#xff0c;以前只要一说啥时啥时考试&#xff0c;下面一片哀嚎声&#xff0c;各种不…

MyBatisPlus(基于starter和Bean方式)

文章目录基于boot-starter方式基于Bean方式基于boot-starter方式 1、【microboot项目】修改配置文件&#xff0c;引入所需要的相关依赖库: dependences.gradle ext.versions [ // 定义所有要使用的版本号springboot : 2.4.3, // SpringBoot版本…

jzoj1013-GCD与LCM【数论】

正题 大意 给出某对数a,b的gcd和lcm&#xff0c;然后求b-a的最小值 解题思路 我们定义A为gcd(a,b)gcd(a,b)&#xff0c;B为lcm(a.b)lcm(a.b)首先我们拿出推lcm的公式 Bab/ABab/A然后移项得 abAB(A≤a,b≤B)abAB(A≤a,b≤B)之后我们就可以枚举了。首先因为只有AA的倍数gcd(a,…

解决Visual Studio For Mac Restore失败的问题

之前就了解到微软出了mac版的VS&#xff0c;没太多的关注&#xff0c;自己也就是使用 DotNet Core SDK VS Code 做一些小demo。 前两天发布了DotNet Core 2.0 &#xff0c;Visual Studio For Mac 7.1 之后&#xff0c;感觉可以装起来用用&#xff0c;把win下面的项目转到Core…

来之不易的美团面试,结果居然挂了...(附面试答案)

转载自 来之不易的美团面试&#xff0c;结果居然挂了...&#xff08;附面试答案&#xff09; 一面 自我介绍 答&#xff1a;自我介绍是面试中唯一的自己主动介绍自己的环节&#xff0c;一定要好好把握好&#xff0c;你数据结构学的号可以手撕一个红黑树你就说我数据结构掌握…

三班的孩子们,你们现在还好吗?

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注公众号【雄雄的小课堂】。三班的孩子们&#xff0c;你们还好吗&#xff1f;虽然已经就业&#xff0c;但还是会时不时的想起你们来&#xff0c;希望你们过的一切都好&#xff0c;在公司中也能快速适应。上午拿着电脑准备去四班上…

AOP案例(日志)

Logs 实体类 Data NoArgsConstructor AllArgsConstructor ApiModel public class Logs implements Serializable {private static final long serialVersionUID -89998567097386518L;/*** 日志ID*/ApiModelProperty(hidden true)private Integer opid;/*** 操作时间*/ApiMod…

jzoj1164-求和【欧拉函数,数论】(筛欧拉函数模板)

正题 大意 给出一个nn,求1&#x223C;n" role="presentation" style="position: relative;">1∼n1∼n里面和nn互质的数的和。解题思路&#x03C6;(i)" role="presentation" style="position: relative;">φ(i)φ(…

升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署

概述 容器&#xff0c;顾名思义是用来存放并容纳东西的器皿&#xff1b; 而容器技术伴着Docker的兴起也渐渐的映入大家的眼帘&#xff0c;它是一个抽象的概念&#xff0c;同时也是默默存在世上多年的技术&#xff0c;不仅能使应用程序间完全的隔离&#xff0c;而且还能在共享…