UWP開發-重新理解MVVM

来源:http://www.cnblogs.com/Yixin-ran/archive/2016/11/24/6097744.html
-Advertisement-
Play Games

MVVM是一個比較熱門的開發框架,儘管已經出現很久了,仍然比較受歡迎。MVVM框架包括: M:Model;Model指的是數據模型,例如你要在頁面展示聯繫人信息,那麼Model就是聯繫人的模型,包括聯繫人的名字,電話號碼,頭像等。。。 V:View;View指的是展示的頁面,比如你所現在看到的這篇文 ...


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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、ASP.NET 中的 Web API [水煮 ASP.NET Web API2 方法論](1-1)在MVC 應用程式中添加 ASP.NET Web API 與 ASP.NET MVC 在同一個進程中使用 ASP.NET WEB API [水煮 ASP.NET Web API2 方法論](1-2) ...
  • 這幾天在Python程式員的微信訂閱號中總是見到yield的關鍵字,才想起來在C#中也是有yield,但是只是知道有,從來沒有瞭解過他的用法,今天有時間就來看看是怎麼使用的。剛開始肯定就是搜索一下用法了,找到兩篇說明示例,一是 C# 中的"yield"使用,第二個是MSDN的官方api yield( ...
  • 這篇文章主要介紹了C#中AS和IS關鍵字的用法的相關資料,需要的朋友可以參考下 ...
  • 頁面引用相應的js以及css 因為SpreaJS是用jquery操作的所以要引用一個jquery的js,第二個js以及最後的css是SpreaJS本身需要引用的,第三個js是做列印才會用到的。 html里只需要放一個div就可以了,相當於SpreaJS的容器。 <div id="ss" style= ...
  • 一、前言 1.0、由於沒有寫過那種通用爬蟲的框架,就四處搜了一下,也找到很多資料,這裡就採用了其中一個大神介紹的框架模式。具體引用地址我忘記了,這裡就不貼出來了。 2.0、之前說的驗證碼模塊也停了,到時候集合在這個分類一面一起說 二、正文 2.1、框架設計圖 2.2、由上面這張圖可以看出各個模塊之間 ...
  • 感謝您的閱讀。喜歡的、有用的就請大哥大嫂們高抬貴手“推薦一下”吧!你的精神支持是博主強大的寫作動力以及轉載收藏動力。歡迎轉載! 版權聲明:本文原創發表於 【請點擊連接前往】 ,未經作者同意必須保留此段聲明!如有問題請聯繫我,侵立刪,謝謝! 我的博客:http://www.cnblogs.com/GJ ...
  • 完善了下 文件中的文件及文件夾中的複製!如果有更優解決方案請不吝指教 protected void FileDepthCopy(string source, string target) { if (Directory.Exists(source))//判斷源文件是否存在 { if (!Direct ...
  • 常用的一些開源組件整理: 導出Excel報表的插件:NOPI.dll(基於微軟OpenXml實現)開源的作業調度和自動任務框架:Quartz.NET用於大數據搜索引擎的全文檢索框架:Lucene.net微軟針對企業級應用開發的最佳實踐組件:Enterprise Library 5.0國外一個牛人寫的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...