MVVM入门 - 新手倒腾一下午了

2 篇文章 0 订阅
2 篇文章 1 订阅


前几天在小组会议上听祖哥谈起了MVVM这个东西,以前在学校的时候听说过,但是没有真正去接触。听他一说觉得这东西还真有意思!于是乎今天就浅浅地研究了一下,其间也得到了祖哥的帮助!在此感谢(虽然你一定看不到这篇文章- -)

 

1.什么是MVVM

这个大家随便谷歌一下就是一大把: Model - View - ViewModel ,它是微软推出的一个框架,可以形象地理解成,我们一开始想盖房子,不知道从哪开始,可能一会堆个墙,一会又铺个地。现在微软就出现了,然后告诉你,其实应该这么盖云云,然后你照他的话做了,嘿,还真那么回事,感觉不会乱了,一切都有秩序了,一口气能上五楼!所以说理解这个框架,对我们的开发都是很有好处的,对开发的效率,以及后期的维护都有帮助。这个MVVM啊,其实写成 View - ViewModel - Model更实在。为啥呢?我就来按照这个VVMM的顺序给大家介绍一下。

2 View

顾英文思中文,是视图的意思,说白了就是你看到的东西,包括静态图片空间什么的和动画效果什么的。放在WindowsPhone开发中,就是我们的界面,就是那个Xaml文件中定义的东东。之所以把这位大哥放在VVMM的首位,是因为我们映入眼帘的就是这玩意。

一般来说,我们会把什么onclick函数啊直接放在xaml对应的cs文件中,进行一些对数据的更改等操作。而MVVM框架跟你说,你这样写不对,或者说不好,来,我跟你说怎么写好。Ok,我们继续往下走。

3 ViewModel

我等菜鸟:不好?哪不好了?

MVVM:你看,你都把数据和界面搅到一起了,多乱啊。万一以后要改数据,或者说要绑定数据库,甚至于要实现多语言全球化,你咋办?你说啊你说啊!

我等菜鸟:……

所以说,MVVM提倡的就是把数据从界面中抽离粗来,分离成数据的模型(Model)。而连接数据和界面的桥梁,的红娘,的老鸨(- -)就是ViewModel。它主要做的是接收用户对界面的操作并做出响应,并在需要时修改Model中的数据。

4 Model

模型,啥叫模型,啥的模型?好吧,大家写过类不?类不就相当于一个模型嘛~但是MVVM中的模型还要高端一些,因为要实现某些功能。嘿嘿嘿。

 

好了,基本概念就这些。我们来看一些代码吧!

先看View!

         <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <TextBox x:Name="txbContent" 
            HorizontalAlignment="Left" Height="114" 
            TextWrapping="Wrap"
            Text="{Binding Zhangsan.Name,Mode=TwoWay}" VerticalAlignment="Top"
            Width="222" Margin="10,72,0,0" />
            <TextBox HorizontalAlignment="Left" Height="72" 
                             TextWrapping="Wrap" Text="{Binding Zhangsan.Price,Mode=TwoWay}"
                     VerticalAlignment="Top" Width="242"/>
            <Button x:Name="btnBigSave" Content="Button" HorizontalAlignment="Left"
          Margin="273,336,0,0"
          VerticalAlignment="Top" 
          Command="{Binding SaveCommond}" />
        </Grid>


 


简单点就是在一个Grid里放点控件。这里我把两个Text绑定到一个变量的属性上,一会大家会看到那个Zhangsan是个啥玩意。mode也得写成TwoWay,这个表示当后台数据更改时,Ui上的字符也随之更改;而更改Ui上的字符时,后台数据也会更改。还有一点就是Button里有一个Command的属性,我也给绑定到了一个SaveCommand的变量上。

这些代码,大家可以当成是View的构成了!

 

再看Model!

虽然ViewModel是桥梁,但是我还是把两头的东西先说清楚。


 

public class Phone : INotifyPropertyChanged
    {
        private int _price;
        public int Price
        {
            get { return _price; }
            set
            {
                _price = value;
                OnPropertyChanged("Price");
            }
        }
 
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged("Name");
            }
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void OnPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }



这个是我创建的类,叫Phone,里面两个属性Price和Name。这边要注意的是一定要实现这个INotifyPropertyChanged接口,然后那个OnPropertyChanged函数也是要加上的,再在Name和Price的set里添加上那句调用函数的代码。这是数据绑定的知识,实现这个接口后,如果你的属性发生了变化(set了),就会调用那个函数,函数就会发出一个事件,表示我的值改变了,然后UI就会自动去更改和这两个属性绑定的控件中的文字(就是前面的两个TextBox)。
 

好的,最后来看ViewModel (现在MainPage.cs里的构造函数加一行 Datacontextt = new MainViewModel();)

 

class MainViewModel : INotifyPropertyChanged
    {
 
        private Phone _p = new Phone() { Name = "wang min rui", Price = 1 };
 
        public Phone Zhangsan
        {
            get { return _p; }
            set
            {
                _p = value;
                OnPropertyChanged("Zhangsan");
            }
        }
 
        public DelegateCommand SaveCommond { get; set; }
 
        public MainViewModel()
        {
            SaveCommond = new DelegateCommand((obj) => SaveFile());
        }
 
        private void SaveFile()
        {
            Zhangsan = new Phone() { Name = "chengjian", Price = 2 };
        }
 
        public event PropertyChangedEventHandler PropertyChanged;
 
        private void OnPropertyChanged(string info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
    }


 


他里面有一个变量,叫做Zhangsan,就是一个Phone,在View中我是把两个TextBox和它的两个属性绑定起来的。其他原理同上。需要注意的是那个DelegateCommand是个啥呢?它是我弄的一个工具类

public class DelegateCommand : ICommand
    {
        public Action<object> ExecuteAction { get; private set; }
 
        public Func<object, bool> CanExecuteFunc { get; private set; }
 
        public DelegateCommand(Action<object> execute, Func<object, bool> canExecute = null)
        {
            if (execute == null)
            {
                throw new ArgumentNullException("execute can not be null!");
            }
            this.ExecuteAction = execute;
            this.CanExecuteFunc = canExecute;
        }
 
        public bool CanExecute(object parameter)
        {
            if (this.CanExecuteFunc != null)
            {
                return this.CanExecuteFunc(parameter);
            }
            else
            {
                return true;
            }
        }
 
        public event EventHandler CanExecuteChanged;
 
        public void Execute(object parameter)
        {
            if (this.CanExecute(parameter))
            {
                this.ExecuteAction(parameter);
            }
        }
    }



相当于一个Command的模板。这个时候我觉得有必要来说一下Command是个啥了。上面说了一般我们会直接实现Onclick函数,但是为了要分离数据和界面,我们使用Button的Command属性,将Button的点击行为绑定到一个Command上。而正好有一个接口叫做ICommand,只要实现它的类,都得实现CanExecute和Execute方法,一个表示是否要响应用户的操作(如点击),另一个表示响应函数要做的事。所以在View中我将Button的Command绑定到了SaveCommand上。而这个类DelegateCommand正是用来生成各种Command的模板类。它的构造函数接受两个函数作为参数,一个作为Execute,另一个作为CanExecute。

 

好了,现在大功告成! 说一下整个的流程:

1)用户打开应用,发现这个很挫的界面。。。

2)由于两个TextBox是和Zhangsan绑定的,所以一开始他们就会显示Zhangsan的两个属性的值(我们在ViewModel中初始化了,看到没)。

3)用户出于蛋疼心理点击了一下Button。

4)由于Button已经和SaveCommand绑定了,所以直接跳到ViewModel中执行SaveCommand的Execute函数,就是我用lambda表达式传进去的SaveFile,在后台改变它的值。

5)因为两个TextBox和Zhangsan的两个属性是通过TwoWay的模式绑定的,所以后台的改变直接导致Ui界面上的改变,此时TextBox上已经显示了chengjian 2

6)各种通知都是通过INotifyPropertyChanged这个接口去传达并改变的。不要看代码中没有显示地去调用一些改变TextBox的Text属性的代码,但是,它就是变了!

 

嗯,就是这样。。。。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值