> For the complete documentation index, see [llms.txt](https://jen-hsuan-hsieh.gitbook.io/design-pattern/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jen-hsuan-hsieh.gitbook.io/design-pattern/chapter1.md).

# Chapter1: MVVM

## This section contain the following items:

* 1.MVVM (Model-View-ViewModel)
* 2.MVVM Example: META (MOXA Engineer Test Application
* 3.Two-Way Binding

## 1.MVVM (Model-View-ViewModel)

1.MVVM的優點是?

* 將與資料有關,及與UI有關的關注點分離
  * 把"狀態"跟使用者"介面"分開
  * 當對一個類別的改變需要牽動其他兩個類別, 而又會引起更多改變時, 這種現象稱為"shotgum surgery", 關注點分離可以防止這種問題的發生
* code能被重複使用
  * 例如我有很多個頁面, 但他們所binding的model並不全都100%相同, 如果有ViewModel
    * this.DataContext = this.plan\_ChidWindow\_NewTestPlan\_ListBoxViewModel;
  * Model, View可被重新使用

2.MVC跟MVVM的差別是?

* 角色 (Role):
  * Model (模型)
    * 用來表示與實作出應用程式內的各種資料物件，並且包含了商業處理邏輯。
  * View (檢視)
    * 表示應用程式中的使用者介面(UI)所要顯示的各個元件。
  * Controller or ViewModel
* MVC
  * 以 Model-View-Controller 來表示
  * Controller: 實踐了策略模式
    * 使用者接觸的對象用來處理使用者的互動與處理資料模型物件, 負責改變Model的狀態或是改變View的顯示
  * View:實踐了合成模式
    * 將內容顯示給使用者,要顯示的內容則是由Model取得
  * Model:實踐了觀察者模式
    * 當Model更新時,相關物件也會持續更新![](/files/-M4M0Lmv6WIuKphiGcaJ)
* MVVM
  * 以 Model-View-ViewModel 來表示
  * View: 通常會需要使用到 XAML 標記宣告語言來定義,而 XAML 僅僅提供了使用者介面的宣告,並無法提供任何處理邏輯
  * ViewModel:扮演這存取資料模型的責任,並且透過了資料繫結技術將資料提供給檢視。
  * 檢視僅知道檢視模型的存在,檢視模型僅知道模型的存在,而檢視模型並不知道檢視的存在,檢視也不知道模型的存在,因此充分做到的關注點分離的目的。

    ![](/files/-M4M0Lmx7J47GH_J6iDs)

3.Model, View, ViewModel: ![](/files/-M4M0Lmzu47MrVU2k2zz)

1\) Model :

* 儲存/產生資料, 通常來自服務或是資料庫
* 宣告軟體的核心函式(自己需要使用到的函式/其他物件所要用到的函式), 至於使用這些函數的時機,也可以透過宣告或是import Model到ViewModel中再使用
* Model記錄app目前的狀態,經常利用事件告訴app的其他部份狀態發生改變

  2\) View :
* 使用者直接與之互動的任何物件
* View可分為以下兩種: 1.User Control: (1)製作Template: 訂出將來所會綁定的Property, 觸發事件(需宣告在code behind中) (2)加入資料來源: 一般來說會將專案中所有的ViewModel用StaticResource放入

  ```
       xmlns:viewmodel="clr-namespace:WatchEample.ViewModel">
      <UserControl.Resources>
        <viewmodel:StopWatchViewModel x:Key="viewModel" x:Name="viewModel" />
      </UserControl.Resources>
      <Grid DataContext="{StaticResource ResourceKey=viewModel}">
    2.Page/Window:
      引用User Control, 以達到將視圖模組化的目的
      xmlns:view="clr-namespace:WatchEample.View">
      <view:BasicStopWatch Grid.Row="1" />
  ```

  3\) ViewModel :
* 具有能夠被繫結到View裡頭之控制項的特性&#x20;
* User Control不可放進ViewModel
* 與Model溝通 (1)建立Model與View間的溝通介面:包裝/使用Model所Release的函式 (2)建立所有與視圖有關的Class: 例如converter (3)Model內先定義好OnEventTrigger, 並寫好發動OnEventTrigger的時機; ViewModel則定義EventHandler, 並向Model註冊
* 與View溝通 雙向綁定: ViewModel本身implement INotifyPropertyChanged: (1)宣告: public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler propertyChanged = PropertyChanged; if(propertyChanged != null){ propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } (2)觸發: 將會讓View中所綁定的欄位發生改變 OnPropertyChanged("LapSeconds"); ![](/files/-M4M0Ln0wRZg_Gx2wJfg)

  **2.MVVM Example**
* 1.需求
  * 要能達到以下的需求:
    * 1.可以做多台機器, 多種Model的測試
    * 2.可以得到realtime的測試情形
    * 3.使用者可以修改/編輯test plan
    * 4.使用者可以擴充test case
    * 5.測試完後可以自動產出test report
      * ![](/files/-M4M0Ln2zVUX3cW3T0rk)
* 2.WireFrame
  * Stage 2 - META的開發, 開發流程如下:

    ![](/files/-M4M0Ln4dfPi9PyTYArw)
  * 以繪圖軟體描繪出外觀作為後續開發的基礎

![](/files/-M4M0Ln6blx4LEy4H-X5)

![](/files/-M4M0Ln8C-rdRl9HL_oY)

* 3.Markdown & 設計軟體架構
  * 檢視wireframe的設計,在wpf實作上的可行性, 並進行修改及優化
  * MVVM: 1. 視圖模組化, 切換頁面要重新組合時十分便利(策略模式) 2. 無論是單一Window或是User Control會連結到的model數量跟種類都不同, 但是ViewModel可以重複利用 3. 在User Control中再嵌入User Control (合成模式)
  * business logic要放在M, V,還是VM? 個人認為: 1. 與按鈕等與視圖有關的功能:
    * 可放到View
    * 如果還可能被利用到其他視圖中, 則可放到ViewModel
      1. 與資料有關的功能,如產生資料則可放在Model

![](/files/-M4M0LnA7Vv2i9Fnb-a6)

![](/files/-M4M0LnCCXWpuuIFBTSX)

![](/files/-M4M0LnET9SHzg9rvFNp)

* 架構
  * META涵蓋了四個部分: Test Reporter, Test Launcher, Test Editor, Test Scripts Tranfer

![](/files/-M4M0LnGGIFRRY7JThGP)

![](/files/-M4M0LnIMtP_vbSLgwii)

* 4.操作 & 測試
  * 操作流程基本如下:

    ![](/files/-M4M0LnKPg34fREeiZCe)

## 3.Two-Way Binding

1\)何謂雙向綁定?

* WPF透過原生的XAML檔和CodeBehind的cs, 提供了開發者分層的開發環境

  可將程式的運算邏輯與設計分層.一旦View的值被調整, 後方的資料也會被調整; 反之後方設定了值,  &#x20;

  View所顯示的內容也會更著改變,這稱為雙向綁定.

2\)Example:

* 建立一個View, 裡面有Listbox, 裡面放了一個TextBlock, 一個Textbox

  TextBlock及Textbox將連結到同一個資料, 因此若使用者修改Textbox中的數值,

  TextBlock的數值也將跟著改變

3\)Cs:

1. 新增一個class: public class testObj : INotifyPropertyChanged { private string test2 = null; public testObj() { test1 = "1"; test2 = "2"; } public string Test2 { set { test2 = value; OnPropertyChanged(new PropertyChangedEventArgs("Test2")); } get { return test2; } } protected void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) { PropertyChanged(this, e); } }

   ```
         #region INotifyPropertyChanged 成員
         public event PropertyChangedEventHandler PropertyChanged;
         #endregion
       }
   ```

   2.編輯MainWindows.cs: public partial class MainWindow : Window { public ObservableCollection moduleInfoList = new ObservableCollection(); public MainWindow() { InitializeComponent(); testObj module = new testObj(); this.moduleInfoList.Add(module); this.listBox.ItemsSource = this.moduleInfoList; } } 4)View (MainWindows.xaml):

   * 目的是將TextBlock及Textbox連結到testObj中的Test2, 因此在tag中加入Mode=TwoWay:

     &#x20;   \</Grid.ColumnDefinitions> \</Grid.RowDefinitions> \</DataTemplate > \</ListBox.ItemTemplate> \</ListBox >

Reference:

1\)<http://stackoverflow.com/questions/17967052/wpf-simple-binding-to-inotifypropertychanged-object>

2\)<http://www.codeproject.com/Articles/41817/Implementing-INotifyPropertyChanged>
