WPF – MVVM (二)

29 December 2011 — Written by Sky Chang
#Design Patten#Silveright#WPF

上一篇講到利用Binding來讓View與ViewModel的繫結,還有ViewModel與Model的關係,但離整個MVVM還有一點點的距離,接下來,我們繼續看下去。 ( 感覺好像漫畫連載喔…放心我不會和某獵x一樣拖稿的。 )

Button事件處理

上一篇我們還沒實際處理按下Button的功能,這裡我們實際的處理一下吧。

下面是View的cs檔,我們會建立一個私有的屬性,這個屬性會利用base.context將XMAL那邊實例化的PostsViewModel傳回來,另外,傳回來的物件需要轉型一下;接下來,我們就可以撰寫Button的Click事件,在這邊,我們將新的值"SkyMVVM"這個Title名稱,傳給PostViewModel ( 實際上會寫回到Model裡面 ),當然這樣子Label是不會改變的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WPFMVVM
{
    public partial class MainWindow : Window
    {
        PostsViewModel _postsViewModel;

        public MainWindow()
        {
            InitializeComponent();
            _postsViewModel = (PostsViewModel)base.DataContext;
        }

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            //這裡還沒辦法通知View,告訴View要更改Label的content
            _postsViewModel.PostsTitle = "SkyMVVM";
        }
    }
}

這邊,如果要Label改變,最直接的做法是在Button Click裡面再加上Label.Content = “SkyMVVM”這行,這樣就可以讓Label馬上的改變,但這樣做當然不好啊,第一,這樣就失去了Binding的意義了,第二,這樣做,Button Click就和Label有了很深的關係。

所以最好的做法是,當我們的PostViewModel的PostsTitle改變的時候,自動讓Label的Content去做改變,但要怎樣做呢?

INotifyPropertyChanged

登登豋登!沒錯我們就是要利用INotifyPropertyChanged這個介面,這個介面裡面含有一個PropertyChanged事件,此事件可以更新繫結的目標喔!

所以我們改寫一下ViewModel的程式碼,讓他實作InotifyPropertyChanged,並且寫一個Function ( RaisePropertyChanged ),此function會產生一個事件,並通知繫結的Label更改Content。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace WPFMVVM2
{
    //實作InotifyPropertyChanged
    public class PostsViewModel : INotifyPropertyChanged
    {
        public Posts posts{ get; set;}

        public event PropertyChangedEventHandler PropertyChanged;

        public PostsViewModel()
        {
            posts = new Posts { postsText = "", postsTitle = "Unknown" };
        }

        public string PostsTitle
        {
            get { return posts.postsTitle; }
            set 
            {
                if (posts.postsTitle != value)
                {
                    posts.postsTitle = value;
                    RaisePropertyChanged("postsTitle");
                }
            }
        } 

        //產生事件的方法
        private void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

做到此,我們就成功地讓ViewModel的屬性和Label進行分離了,也就是說ViewModel可以完全不用知道View了!但這樣就算完成MVVM了嗎??還沒還沒,我們繼續看下一篇吧。

參考資料

Sky & Study4.TW