從頭開始:詳解MVVM、MVVMLight


  • 究竟為什么要學習MVVM?

 

相信大部分同學在剛開始接觸MVVM的時候(包括我自己),心里默默在想這究竟是什么玩意?一個簡單的功能要寫一大段代碼才能完成,在看到MVVM的核心目標:

1.讓UI界面與邏輯能夠很好地分離又協同工作。

2.讓邏輯代碼更具有可測試性。

會覺得我不把我的UI和邏輯分離,我的代碼一樣可以很好的分離又協同工作;

會覺得我不用MVVM我的代碼一樣測得好好的;

在這里,我先不說什么。我覺得這個需要自己意會了才能判斷出自己的觀點是正確的還是錯誤的。
  • 開始學習MVVM之前:
1.在開始學習MVVM你應該具備基本的C#(WPF或者SliverLight)的變成知識。如果你現在對這些還不熟悉,不建議先看這個,畢竟凡事都需要一步一步來。

2.本文主要拿WPF程序作為例子。例子源代碼提供下載。
  • 學習綁定(Binding)

1.新建一個WPF項目

2.新建一個類:Model,Model代碼如下:

    class Model
    {
        private string _text;

        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        public Model()
        {
            _text = "HelloWorld";
        }
    }
Model代碼

3.在MainWindows中放一個TextBox:

<TextBlock Text="{Binding Text}"/>
View Code

     TextBox的Text並沒有顯示制定值,而是綁定在一個名為"Text"的變量上面。但是目前這個程序還無法運行,因為編譯器不知道“Text”這個變量是什么東西,所以需要給編譯器指明這個“Text”在哪里。

     我們的目的是要把TextBox的Text屬性綁定在Model類的Text屬性上面,設置數據上下文(DataContext)就可以讓編譯器找到“Text”這個變量。

<Window x:Class="學習綁定.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:學習綁定"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:Model/>
    </Window.DataContext>
    <Grid>
        <TextBlock Text="{Binding Text}"/>
    </Grid>
</Window>
View Code

現在程序應該可以運行了,效果如下:

剛開始學可以簡單粗暴一點,綁定就是把一個值綁定在另一個值上面。綁定也是一個比較復雜的東西,這里不細講,需要了解的朋友可以自己搜索下,太多的資料的。

在你覺得自己了解綁定之后就可以往下看了。

  •  開始第一個MVVM程序

 這個程序很簡單,在界面中放置一個文本框和一個按鈕很簡單。文本框初始化的值為0.在點擊按鈕后,文本框的值加1.

界面XAML如下:

<Window x:Class="第一個MVVM程序.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock x:Name="Tb1"/>
        <Button Click="Button_Click" Content="點擊我加1" Margin="0,10,0,0" HorizontalAlignment="Left"/>
    </StackPanel>
</Window>
View Code

 在沒有了解MVVM之前,我們實現這個的過程很可能是這樣:

public partial class MainWindow : Window
    {
        private int Num;

        public MainWindow()
        {
            InitializeComponent();
            Num = 0;
            Tb1.Text = Num.ToString();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Num++;
            Tb1.Text = Num.ToString();
        }
    }
View Code

實現后運行的效果如下:

 

根據上面學的綁定的知識,我們通過綁定的方式實現這個功能。

1.建立一個類Model

    class Model
    {
        private int _num;

        public int Num
        {
            get { return _num; }
            set { _num = value; }
        }

        public Model()
        {
            _num = 0;
        }
    }
View Code

 2.將文本框的Text屬性綁定在Model的Text上面。(記住聲明DataContext)

綁定之后,程序的Xaml代碼就變成這樣了: 

<Window x:Class="第一個MVVM程序.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:第一個MVVM程序"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:Model/>
    </Window.DataContext>
    <StackPanel>
        <TextBlock x:Name="Tb1" Text="{Binding Num}"/>
        <Button Click="Button_Click" Content="點擊我加1" Margin="0,10,0,0" HorizontalAlignment="Left"/>
    </StackPanel>
</Window>
View Code

 3.然后相應按鈕的響應事件:

public partial class MainWindow : Window
    {
        private Model model;

        public MainWindow()
        {
            InitializeComponent();
            /*Xaml里面通過這樣的方式為窗體添加了一個數據上下文
             * <Window.DataContext>
             *     <local:Model/>
             * </Window.DataContext>
             * 現在由於文本框的值綁定在Model的Text上面了,所有需要獲取這個Model才能改變Text的值,
             * 改變了Text的值才能改變文本框顯示的值
             */ 
            model = this.DataContext as Model;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            model.Num++;
        }
    }
View Code

4.編譯通過,開始運行。點擊按鈕后........媽蛋怎么文本框的值沒有變?其實原因很簡單。

我們先理清楚我們到目前為止在這個程序里面做了什么。

首先,我們建立了一個Model類,並在類里面寫了一個屬性"Text";

然后,我們將TextBlock的Text屬性綁定在了Model的“Text”屬性上面;

最后,我們發現在更改了Model的Text值后,TextBlock的值並沒有發生變化。

可以確定的是,Model類的Text值肯定變化了。既然Model類的Text發生了變化,綁定也綁了,那么TextBlock的值怎么不變化?

實際上是因為你沒有通知界面Text的值變了,所以界面就不知道實際上Model里面的Text已經發生變化,自然就沒有必要更新界面了。

了解了問題產生的原因后,我們需要在Text發生變化后通知界面.為此,類Model需要實現"INotifyPropertyChanged"借口。從字面上就可以發現這個接口的意思就是“通知屬性變化”。

實現后,Model類就變成這樣了:

    class Model:INotifyPropertyChanged
    {
        private int _num;

        public int Num
        {
            get { return _num; }
            set 
            { 
                if(_num != value)
                {
                    _num = value;
                    NotifyPropertyChanged("Num");
                }
            }
        }

        public Model()
        {
            _num = 0;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string name)
        {
            if(PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(name));
            }
        }
    }
View Code

運行后,效果如下:

對於初學者,很難一下理解透這些過程和原理。其實你需要記住:但凡你想要在你的數據源發生變化,目標的值跟着發生變化,你都需要在數據源發生變化的時候通知目標。

未完待續。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM