UWP開發-從新理解MVVM

  MVVM是一個比較熱門的開發框架,儘管已經出現好久了,仍然比較受歡迎。MVVM框架包括:前端

    M:Model;Model指的是數據模型,例如你要在頁面展現聯繫人信息,那麼Model就是聯繫人的模型,包括聯繫人的名字,電話號碼,頭像等。。。框架

    V:View;View指的是展現的頁面,好比你所如今看到的這篇文章都是View。dom

    VM:ViewModel;ViewModel指的是對View的抽象!什麼是抽象? 大概就是它實際是存在的,但你又不能直接"看"到。async

對於這三者的關係,我舉個簡單的例子吧:ide

  假設你喜歡一個姑娘,姑娘都有身高,體重,臉蛋類型等等對吧.this

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

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

private 姑娘 個人姑娘 = new 姑娘 { 體重 = 200, 姓名 = "狗蛋", 臉蛋 = 臉蛋類型.麻子, 身高 = 150 ,IsLike=false};//私有

你一看,臥槽這哪行,趕快滾蛋,從新new一個code

 private 姑娘 個人姑娘 = new 姑娘 { 體重 = 100, 姓名 = "柳言", 臉蛋 = 臉蛋類型.光滑, 身高 = 165,IsLike=true };

喜歡的姑娘有了,但你不知道姑娘是否是也喜歡你呀,因此你想對姑娘表達愛慕,看看姑娘的反應:orm

   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的,其實我就是個剛入門的菜鳥。但願各位大俠輕噴!

相關文章
相關標籤/搜索