专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > WinRT Metro

UWP开发-从新理解MVVM

发布时间:2011-06-23 13:55:03 文章来源:www.iduyao.cn 采编人员:星星草
UWP开发-重新理解MVVM

  MVVM是一个比较热门的开发框架,尽管已经出现很久了,仍然比较受欢迎。MVVM框架包括:

    M:Model;Model指的是数据模型,例如你要在页面展示联系人信息,那么Model就是联系人的模型,包括联系人的名字,电话号码,头像等。。。

    V:View;View指的是展示的页面,比如你所现在看到的这篇文章都是View。

    VM:ViewModel;ViewModel指的是对View的抽象!什么是抽象? 大概就是它实际是存在的,但你又不能直接"看"到。

对于这三者的关系,我举个简单的例子吧:

  假设你喜欢一个姑娘,姑娘都有身高,体重,脸蛋类型等等对吧.

 public class 姑娘
    {
        public enum 脸蛋类型
        {
            光滑 = 0,
            麻子 = 1
        }
        public string 姓名 { get; set; } 
        public double 身高 { get; set; }
        public double 体重 { get; set; }
        public 脸蛋类型 脸蛋 { get; set; }
    }

光有姑娘的概念不行呀,你要的是一个实例,那好,咱new一个

private 姑娘 我的姑娘 = new 姑娘 { 体重 = 200, 姓名 = "狗蛋", 脸蛋 = 脸蛋类型.麻子, 身高 = 150 ,IsLike=false};//私有

你一看,卧槽这哪行,赶快滚蛋,重新new一个

 private 姑娘 我的姑娘 = new 姑娘 { 体重 = 100, 姓名 = "柳言", 脸蛋 = 脸蛋类型.光滑, 身高 = 165,IsLike=true };

喜欢的姑娘有了,但你不知道姑娘是不是也喜欢你呀,所以你想对姑娘表达爱慕,看看姑娘的反应:

   private async Task 表达爱慕()
        { 
            string 骚话 = "骚话不断,我宣你!";
            try
            {
                var 她喜欢我 = await Say(骚话, 我的姑娘);
                var 心情 = 她喜欢我 ? "得意洋洋" : "哭天抢地";
            }
            catch
            {
                Debug.WriteLine("革命尚未成功,同志仍需努力!");
            }
        }
        private async Task<bool> Say(string _word, 姑娘 _girl)
        {
            //此处说完
            await Task.Delay(10000);//姑娘很矜持
            Random R = new Random();
            var res= R.Next(0, 1);
            switch (res)
            { 
                case 1:
                    return true;
                default:
                    return false;
            } 
        }

 上面的姑娘类就是Model,new的姑娘对象和表达爱慕就是ViewModel,你看到姑娘和姑娘给你的反馈就是View。

好了,现在说正经的:

  在正式讲MVVM之前先讲几个重要的知识:Binding,DataContext,INotifyPropertyChanged接口

Binding就是数据的绑定啦,比如你要展示上面姑娘的信息:

     <StackPanel x:Name="profile_SP">
            <TextBlock Text="{Binding 身高,Mode=OneWay}"/>
            <TextBlock Text="{Binding 体重,Mode=TwoWay}"/>
        </StackPanel>

Binding的Mode有三种:OneTime;OneWay,TowWay。OneTime表示绑定这个值以后无法更改;OneWay表示后台的更改前台同步显示,但前台的更改后台不会发生改变,只会改变前台的显示;TwoWay表示无论在哪里的更改都是有效的。默认OneWay

这里的身高和体重就是Binding的Path,Binding还有一个Source属性,这里没有指定,但是在后台需是要指定,不然找不到身高和体重这两个属性了。Binding找数据源是根据控件树一级一级往上找的,如果没找到就会报错。

在后台代码中指定DataContex

profile_SP.DataContext = 我的姑娘;

也可以指定为这个页面的DataContext

this.DataContext = 我的姑娘;

但这样有个问题呀。假如你心仪这个姑娘很久了,你就一直盯着她的资料看,但是,姑娘长膘了,从原来的100长到了150,但你不知道啊,因为你看到的是她原来的资料。这时候就需要实现INotifyPropertyChanged接口来通知前端后台发生了数据更改。

  public class DispatcherManager
    {
        private CoreDispatcher _dispatcher;
        public CoreDispatcher Dispatcher
        {
            get
            {
                return _dispatcher;
            }
            set
            {
                _dispatcher = value;
            }
        }

        private static DispatcherManager _current;
        public static DispatcherManager Current
        {
            get
            {
                if (_current == null)
                {
                    _current = new DispatcherManager();
                }
                return _current;
            }
        }
    }
    public class 姑娘 : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected async void OnPropertyChanged([CallerMemberName]string propertyName = "")
        {
            if (PropertyChanged != null)
            {
                if (DispatcherManager.Current.Dispatcher == null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
                else
                {
                    if (DispatcherManager.Current.Dispatcher.HasThreadAccess)
                    {
                        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                    }
                    else
                    {
                        await DispatcherManager.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                            delegate ()
                            {
                                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                            });
                    }
                }
            }
        }
        public enum 脸蛋类型
        {
            光滑 = 0,
            麻子 = 1
        }
        private double _weight;
        private bool _islike;
        public string 姓名 { get; set; } 
        public double 身高 { get; set; }
        public double 体重
        {
            get { return _weight; }
            set { _weight = value;OnPropertyChanged(); }
        }
        public 脸蛋类型 脸蛋 { get; set; }
        public bool IsLike
        {
            get { return _islike; }
            set { _islike = value;OnPropertyChanged(); }
        }
}

好了现在姑娘长膘了我们可以随时知道,也可以随时”变心“了(都是“善变”的动物)。

  先来看View:

 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="{Binding 姓名}"/>
            <TextBlock Text="{Binding 身高}"/>
            <TextBlock Text="{Binding 体重,Mode=TowWay}"/>
            <TextBlock Text="{Binding 脸蛋}"/>
        </StackPanel>
    </Grid>

很简单,就展示了姑娘的基本信息。

接下来设置ViewModel:

public delegate void MovieWatchEventHander();
        public delegate void 头脑发热EventHandler();
        public event MovieWatchEventHander MovieWatched;//看完一部爱情电影后
        public event 头脑发热EventHandler 头脑发热ed;
        private GrilViewModel _viewModel;

        public GirlPage()
        {
            this.InitializeComponent();
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            if(e.NavigationMode== NavigationMode.New)
            {
                this.DataContext = _viewModel = new GrilViewModel();
                MovieWatched += GirlPage_MovieWatched;
                头脑发热ed += GirlPage_头脑发热ed;
            }
        }

        private async void GirlPage_头脑发热ed()
        {
            await _viewModel.表达爱慕();
        }

        private async void GirlPage_MovieWatched()
        {
            await _viewModel.表达爱慕();
        }

注意这里我为什么不把事件等东西全部放到ViewModel呢?严格按照MVVM来说是的,应该放在ViewModel里,但是,我们不要为了模式而模式,尤其是页面的事件,Button的Click还好说,有Command,但是其他时间要写到MVVM里面就非常麻烦,而这并没有给我们带来明显的好处,所以还是直接放到页面的cs文件中比较好。

  说说我理解的模式吧,就好比一个剑客

第一层:手中无剑,拿一根木棍胡乱打一通;就跟我们开始写代码,不管三七二十一,实现再说;

第二层:手中有剑,会一招一式,此时可以行走江湖,一般来说应付得过来;按照“模式”来;

第三曾:手中无剑,心中有剑,此时就是绝顶高手,杀人于无形;模式变通,无招胜有招;

  哈哈,以上就是我瞎jb吹nb的,其实我就是个刚入门的菜鸟。希望各位大侠轻喷!

9楼vbfool
中文编程又没啥,我们还干过类名属性名方法名接口名都用中文的呢。,,关于事件,可以使用Microsoft.Xaml.Interactivity来发到ViewModel层,或者从ViewModel层发到View层。除非你的事件处理和ViewModel没有任何的耦合,不然你的设计人员做Blend的时候就蛋疼了。
8楼大萝卜卜
第一层:手中有剑,心中无剑,第二层:手中有剑,心中有剑,第三层:手中无剑,心中有剑,第四层:手中无剑,心中亦无剑。。。
Re: Yixin-Ran
@大萝卜卜,蛤?那还写个卵,自己创业当梦想导师去了 _0.0_
7楼Nicoplus
有意思,哈哈。能转吗
Re: Yixin-Ran
@Nicoplus,注明出处就可以了
6楼有趣之极
有意思,以前用silverlight搞过绑定。
5楼h82258652
这中文编程把我吓尿了
Re: Yixin-Ran
@h82258652,@ExperDot,编程无国界呀 啊哈
4楼J耳朵
引用有点搞
3楼ExperDot
中文变量很懵逼#128514;
2楼zhxiao
挺好玩的 不过中间不够细,太长就没看了...
1楼ExperDot
@vbfool,中文编程第一观感是反直觉,用惯了自然没什么。若是开源项目,外国人就要大眼瞪小眼了
友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: