1. 程式人生 > >MVVM開發模式例項解析

MVVM開發模式例項解析

此例項為本人依託網上原有資料,加以個人理解整合,在MVVM模式下寫的一個基於MySQL資料庫的小Demo,實現對資料庫中內容的搜尋顯示功能。文件下載 原始碼下載

本例項基於VS2012+MySQL+SilverLight5實現。

MVVM開發模式

概述

MVVM(Model-View-ViewModel)是在WPF/Silverlight一種很常見的開發模式,是MVC模式的一種變種,從字面意義上便可知MVVM模式大致上可以分為三個模組即Model、View和ViewModel。Model(模型)層主要存放一些實際資料,業務邏輯程式碼, View(檢視)就是與使用者互動的介面層,存放著我們的Xaml頁面,而通過Xaml頁面控制元件的Binding技術就能夠實現View和Model之間的關聯,但實際程式設計時我們發現, Model中的屬性(與方法)往往不那麼容易與View中的介面控制元件關聯起來, 比如型別不匹配介面控制元件所需要的型別與模型中屬性提供的型別不匹配,也就是說需要額外操作,模型中的資料需要經過一些額外的處理才能傳給檢視,這誕生了我們的ViewModel模組,ViewModel檢視模組層的作用用來連線業務邏輯和檢視層的關鍵部分,通常我們發出的命令或者事件都是通過這層傳送給業務邏輯層的。這樣MVVM模式解決了,我們在開發WPF/Silverlight應用程式過程中產生的業務層、表示層比較混亂問題,使表示層和業務層完全分離。

由於我們的silverLight專案無法直接連線MySQL資料庫,通常的做法是通過Web Service和WCF服務,所以在對資料庫的操作將放到web專案中,然後通過silverLight中引用相應的服務便可間接時間對資料庫的訪問。

例項演示

新建一個silverLight應用程式MVVMDemo, 生產解決方案後會有兩個專案,一個是silverLight的專案,一個是以silverLight專案名加.web的專案。

資料庫層

專案主要功能:實現對資料庫中的使用者根據使用者名稱的模糊查詢。

資料庫的設計:資料庫名:db_user,表名:t_user, 詳細見下圖:


在silverLight專案中新建四個資料夾,分別是Model, View, ViewModel和Command,Command我們用來存放的命令,Model我們用來存放獲取到的資料,View我們用來存放顯示查詢的UserControl,ViewModel用來實現相應資料和命令的繫結。在web專案中新建Entiyi資料夾用來存放資料庫實體類(User),同時在web專案下新建一個操作資料庫的類SQLHelper和一個提供給SilverLight專案執行使用者資訊相關操作的web服務,UserInfoWebService.asmx截圖如下:


要使用MySQL資料庫,首先需要下載安裝mysql-connector-net-6.6.4,然後在web專案中引用安裝目錄下的MySql.Data.dll, 然後再Web.config配置連線字串如下:

<appSettings>

<addkey="ip"value="localhost"/>

<addkey="port"value="3306"/>

<addkey="user"value="root"/>

<addkey="pwd"value="teamwork603_04"/>

<addkey="database"value="db_user

"/>

<addkey="encoding"value="utf8"/>

<addkey="parseType"value="HTML"/>

</appSettings>

這樣在SQLHelper類中再引用MySql.Data.MySqlClient; System.Configuration;便可實現對資料庫的訪問,在此就不貼上具體實現程式碼。

然後在UserInfoWebService.asmx中便可以通過呼叫SQLHelper類中的方法進一步封裝成類集合供silverLight專案呼叫,在UserInfoWebService.asmx寫入以下方法。

[WebMethod]

publicList<User>GetUserByName(string sqlStr)

{

List<User> userList = newList<User>();

SQLHelpersqlHelper = newSQLHelper();

DataSetuserDataSet = sqlHelper.QueryData(sqlStr);

foreach (DataRow dr in userDataSet.Tables[0].Rows)

{

Useruser = newUser(Convert.ToInt32(dr[0]), Convert.ToString(dr[1]));

userList.Add(user);

}

return userList;

}

這樣一個根據使用者名稱查詢使用者的web服務方法便完成了,接下來再silverLight的專案中引用—>新增服務引用—>發現,然後選後剛剛的UserInfoWebService.asmx,即可,如圖:


可以修改名稱空間為UserInfoServiceReference,在silverlight的專案中你會發現多出了一個Service References的資料夾,資料夾裡面就是引用的服務。

View層

到了這步,對資料庫部分的工作就大致完成了,結下了就是通過MVVM模式來實現查詢了。

首先在View資料夾下新建一個Xaml頁面,使用者提供查詢的介面,如下圖:


也就是一個文字框,一個按鈕,和一個顯示結果的DataGrid,程式碼在後面。

ViewModel層

我們可以看到有三個控制元件,為了在ViewModel層實現繫結,需要在ViewModel層分別為這三個控制元件定義相應的屬性, 在文字框輸入查詢字元後文本框的文字屬性就變化,查詢到資料後更新到DataGrid後相應的屬於也會變化, 要實現屬性變化的通知就需要實現INotifyPropertyChanged 介面,INotifyPropertyChanged介面定義了一個當屬性值改變時執行的事件,名稱為PropertyChanged,這是繼承這個藉口必須要實現的事件, event PropertyChangedEventHandler PropertyChanged; PropertyChangedEventHandler委託類delegate voidPropertyChangedEventHandler(object sender, PropertyChangedEventArgs e); PropertyChangedEventArgs型別,這個類用於傳遞更改值的屬性的名稱,實現向客戶端已經更改的屬性發送更改通知,屬性的名稱為字串型別。根據PropertyChanged事件的委託類,實現PropertyChanged事件:

PropertyChanged(this, new PropertyChangedEventArgs("PropertyName"));

綜上,可在ViewModel中新建一個QueryUserViewModel類,繼承INotifyPropertyChange介面,定義查詢關鍵字和查詢結果兩個變數,並實現相應的屬性更改事件:

#region屬性

///<summary>

///查詢關鍵字

///</summary>

publicstring SearchText

{

get { return _SearchText; }

set

{

_SearchText = value;

if(PropertyChanged != null)

{

this.PropertyChanged(this, newPropertyChangedEventArgs("SearchText"));

}

}

}

///<summary>

///查詢結果

///</summary>

publicObservableCollection<User> ResultText

{

get { return _ResultText; }

set

{

_ResultText = value;

if(PropertyChanged != null)

{

this.PropertyChanged(this, newPropertyChangedEventArgs("ResultText"));

}

}

}

接下來還有按鈕事件的繫結,按鈕具有Command屬性,實現自定義命令需要繼承ICommand介面。在該介面中定義了一個event EventHandler CanExecuteChanged事件,當出現影響是否應執行該命令的更改時發生,bool CanExecute(object para)方法,定義用於確定此命令是否可以在其當前狀態下執行的方法。以及void Execute(object para)執行此命令時呼叫的方法。這樣就需要在ICommand檔案加下新增一個QueryUserCommand類,用於自定義命令,通過委託執行ViewModel中的SearchUserByUserName方法

///<summary>

///定義Action委託

///</summary>

privateAction _Handler;

publicQueryUserCommand(Action Handler)

{

this._Handler =Handler;//委託方法

}

///<summary>

///當出現影響是否應執行該命令的更改時發生。

///</summary>

publiceventEventHandlerCanExecuteChanged;

///<summary>

///定義用於確定此命令是否可以在其當前狀態下執行的方法。

///</summary>

///<paramname="para"></param>

///<returns></returns>

publicboolCanExecute(object para)

{

if (para != null)

{

CanExecuteChanged(para, newEventArgs());

}

returntrue;

}

///<summary>

///定義在呼叫此命令時呼叫的方法。

///</summary>

///<paramname="para"></param>

publicvoid Execute(object para)

{

_Handler(); //呼叫委託

}

所以在QueryUserViewModel類中,還需要新增一個按鈕的Command屬性,

///<summary>

///查詢命令

///</summary>

publicICommand SearchCmd

{

get { return_SearchCmd; }

         }

以及屬性執行的方法,和在建構函式關聯委託執行的方法_SearchCmd = newQueryUserCommand(SearchUserByUserName);

Model層

接下來就可以通過呼叫Model的資料來資料和命令的關聯了,Model層主要是通過對Web專案中資料的提取來獲得資料,而在UserInfoWebService.asmx類中提供了一個web方法GetUserByName,可以通過此方法的相應事件在Model層實現呼叫,所以接下來在Model層中新建一個UserHandle類,一下函式實現對Web方法的呼叫:

///<summary>

///獲取使用者

///</summary>

///<paramname="userName"></param>

publicvoidgetUserList(string userName)

{

userName = "%" + userName+ "%";

string sqlStr = "select* from t_user where user_name like '" + userName + "'";

UserInfoWebServiceSoapClientuserInfoClient = newUserInfoWebServiceSoapClient();

userInfoClient.GetUserByNameCompleted += newEventHandler<GetUserByNameCompletedEventArgs>(userInfoClient_GetUserByNameCompleted);

userInfoClient.GetUserByNameAsync(sqlStr);       

}

可以看到,編譯器自動給我們的Web方法添加了一耳光Completed結尾的事件,和一個執行函式以Async結尾,我們在這裡需要為Completed事件新增一個函式,用來傳遞執行查詢完成後資料的回傳到客戶端,名字為userInfoClient_GetUserByNameCompleted的函式,為了實現自動回傳到ViewModel層,需要定義一個委託和相應的事件,

///<summary>

///完成獲取使用者

///</summary>

///<paramname="sender"></param>

///<paramname="e"></param>

publicvoiduserInfoClient_GetUserByNameCompleted(object sender, GetUserByNameCompletedEventArgs e)

{

userList = e.Result;

getUserListEvent(userList);//觸發事件,傳遞獲取到的使用者

}

///<summary>

///定義處理獲取使用者完成後的委託

///</summary>

///<paramname="userList"></param>

publicdelegatevoidGetUserListEventHandle(ObservableCollection<User>userList);

///<summary>

///將委託和事件關聯

///</summary>

publiceventGetUserListEventHandlegetUserListEvent;

然後再ViewModel層的QueryUserViewModel類中的建構函式中新增相應的事件執行函式實現資料的收和反饋到介面:

userHandle.getUserListEvent += new UserHandle.GetUserListEventHandle(SetResult);

這樣整個機制就大體完成了,接下來就是介面的程式碼:

<UserControl

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="MVVMDemo.View.QueryUser"

xmlns:vm="clr-namespace:MVVMDemo.ViewModel"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="400">

<UserControl.Resources>

<vm:QueryUserViewModel x:Key="QUVM"/>

</UserControl.Resources>

<Grid x:Name="LayoutRoot"Background="White" DataContext="{StaticResource QUVM}" >

<Button Content="查詢"HorizontalAlignment="Left" Margin="191,36,0,0"VerticalAlignment="Top" Width="75" Command="{Binding SearchCmd}"/>

<TextBox HorizontalAlignment="Left" Height="23" Margin="37,35,0,0" TextWrapping="Wrap" Text="{Binding SearchText, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>

<sdk:DataGrid HorizontalAlignment="Left" ItemsSource="{Binding ResultText}" Height="108" Margin="37,97,0,0"VerticalAlignment="Top" Width="229"AutoGenerateColumns="False"AlternatingRowBackground="BlanchedAlmond">

<sdk:DataGrid.Columns>

<sdk:DataGridTextColumn Header="ID" Binding="{Binding ID}" Width="50" ></sdk:DataGridTextColumn>

<sdk:DataGridTextColumn Header="Name" Binding="{Binding Name}" Width="100"></sdk:DataGridTextColumn>

</sdk:DataGrid.Columns>

</sdk:DataGrid>

</Grid>

</UserControl>

執行介面:

個人觀點

自認為對此開發模式最好部分就是通過繫結實現了前臺和後臺的分離,在實現上多采用事件和委託機制,對於不理解事件和委託的同學來說會理解整個架構的流程會比較困難,個人覺得整個系統框架寫得比較複雜,其中還有很多不規範和不完善以及冗餘的地方以後完善。


相關推薦

MVVM開發模式例項解析

此例項為本人依託網上原有資料,加以個人理解整合,在MVVM模式下寫的一個基於MySQL資料庫的小Demo,實現對資料庫中內容的搜尋顯示功能。文件下載 原始碼下載 本例項基於VS2012+MySQL+SilverLight5實現。 MVVM開發模式 概述 MVVM(Mod

Asp.net MVC 中 CodeFirst 開發模式例項

  昨天寫的這篇部落格因為下班時間到了忘記儲存了,好鬱悶,得重新寫一遍。實習所在公司使用的是CodeFirst開發模式,最近開始參與到公司的專案裡面來了,發現這個模式特別好用,建庫建表改變欄位屬性新增刪除欄位等等操作都無需自己在資料庫動手操作,只需要編寫程式碼即可實現,著實是方便了許多。今天來記錄一下如何使用

玩轉Android之MVVM開發模式實戰,炫酷的DataBinding!

C# 很早就有了MVVM的開發模式,Android手機中的MVVM一直到去年Google的I\O大會上才推出,姍姍來遲。MVVM這中開發模式的優點自不必多說,可以實現檢視和邏輯程式碼的解耦,而且,按照Google的說法,使用了MVVM的開發模式,還可以提高佈局檔案的解析速度,

WPF的MVVM開發模式 與 databinding 和commandbinding

既然講到MVVM模式,自然第一個問題就是MVVM的含義。MVVM是Model-View-ViewModel的縮寫形式,它通常被用於WPF或Silverlight開發。模型(Model)  Model——可以理解為帶有欄位,屬性的類。檢視(View)  View——可以理解為我

互助模式案例解析 互助系統開發

註冊 激活碼 2個 直接 獲得 賬號 高級 停止 每次 會員與利息: M1會員升級條件:新註冊用戶,日息:排隊1%,打款後2%,推薦獎及代數:拿1代,6%,經理獎:0,每月排單數:1-3 M2會員升級條件:團隊3人,日息:排隊1%,打款後2.2%,推薦獎及代數:拿2代,6%

某某鏈互助分紅模式案例解析,互助分紅系統開發

無限 自己 玩家 配對 賬號 優先 直接 系統 透明 一.註冊需要個人真實姓名、手機號、推薦人賬號;一個手機號碼只能註冊一個賬戶。二.免費註冊,註冊成功後每個賬號需要一張門票,300元/個,轉門票激活確定分享關系。下級需要推薦人通過轉門票方式確定分享關系。 小於6000元需

江湖蜜集拆分遊戲模式制度解析,農場遊戲開發

註冊 好友 江湖 制度 之間 添加 強調 遊戲開發 獎勵 江湖蜜集可以築建15個蜂巢,按地塊顏色以次築建,地塊分為綠色土江湖蜜集可以築建15個蜂巢,按地塊顏色以次築建,地塊分為綠色土巢的基數作為不動產是不可交易的。 綠色土地每塊地築建蜂巢需要倉庫有300只蜜蜂,且養蜂上限為

互助盤模式案例解析,互助系統開發

負責 提現 信息 四個月 協助 支付 註冊 兩種 免費註冊 一:靜態收益2%/天投資額60到100000元之間, 月固定收益都是60%利息!當有人需要資金幫助時,你就可以把你的資金打給對方!當你需要資金幫助時,你就可以在平臺內提出申請,等待別人幫助。就這樣,不斷的提供互助和

Linux 裝置驅動開發 —— platform裝置驅動應用例項解析

       前面我們已經學習了platform裝置的理論知識Linux 裝置驅動開發 —— platform 裝置驅動 ,下面將通過一個例項來深入我們的學習。 一、platform 驅動的工作過程         platform模型驅動程式設計,需要實現platfor

C#.架構設計(三)MVVM架構模式(用在WPF或Silverlight)、MVC架構模式(用在java開發)、MVP架構模式(用在安卓開發)的原理與區別

轉發https://blog.csdn.net/victoryzn/article/details/78392128 本文將詳細闡述以下MVC、MVP、MVVM三種理念的定義及區別還有他們的適用場合。 MVC MVC模式最初生根於伺服器端的Web開發,後來漸漸能夠勝任客戶端Web開發,能

WebSphere MQ Java 應用開發簡單例項(上篇:客戶端模式開發)(client mode和binding mode)

1-背景知識 IBM MQ支援多種語言開發,本文主要是考慮Java應用開發,MQ提供了相關的Java類庫,可以很方便整合到Java應用中。 IBM MQ Java相關類庫允許Java應用直接與佇列管理器互動,或者連線MQ伺服器和客戶端進行互動。 類庫主要有

解析 Visual Studio 2017 核心理念及其背後開發模式

陽春三月,正逢 Visual Studio 20 週歲之際,微軟釋出了備受期待的 Visual Studio 2017。新版的 Visual Studio 不僅帶來了一個新的輕量化和模組化的安裝體驗,依需要量身定製安裝,還對於開發、除錯、測試、寫作、擴充套件等原

例項學習WPF的MVVM程式設計模式1

    先看一下程式介面,要實現的功能很簡單,輸入一個數,然後點選按鈕,將輸入數的平方根結果顯示在上方。     不使用MVVM模式,在Calculate按鈕的Click事件中,編寫程式碼,將結果顯示到上方的TextBlock中。     現在,我們來一步步實現MVV

java 開發模式之十九 :解析模式

原理或定義 給定一個語言,定義它的文法的一種表示,並定義一個直譯器,這個直譯器使用該表示來解釋語言中的句子。屬於行為類模式 結構 AbstractExpression:宣告一個抽象的Interpret方法,抽象語法樹中所有的節點都必須實現該抽象方法。 TerminalExp

android中MVC,MVP和MVVM三種模式解析

我們都知道,android本身就採用了MVC模式,model層資料來源層我們就不說了,至於view層即通過xml來體現,而 controller層的角色一般是由activity來擔當的。雖然我們專案用到了MVP模式,但是現在人們並沒有總結出一種規範,所以MVP模式的寫法並不

Android開發之位置定位詳解與例項解析(GPS定位、Google網路定位,BaiduLBS(SDK)定位)

/** * 由經緯度獲取所在的城市及區域資訊 * @author caizhiming * */ private class ReadJSONFeedTask extends AsyncTask<String, Void, String> {

Android開發模式之MVC,MVP和MVVM的簡單介紹與區別

相信大家對MVC,MVP和MVVM都不陌生,作為三個最耳熟能詳的Android框架,它們的應用可以是非常廣泛的,但是對於一些新手來說,可能對於區分它們三個都有困難,更別說在實際的專案中應用了,有些時候想用MVP的,程式碼寫著寫著就變成了MVC,久而久之就對它們三個的選擇產生了

Vue-MVVM模式-簡單解析

Vue.js介紹Vue.js是當下很火的一個JavaScript MVVM庫,它是以資料驅動和元件化的思想構建的。相比於Angular.js,Vue.js提供了更加簡潔、更易於理解的API,使得我們能夠快速地上手並使用Vue.js。如果你之前已經習慣了用jQuery操作DOM

三大開發模式的介紹(MVC、MVVM、MVP)

一.MVC:Model - View - Controller 特點:各部分迴圈傳遞 流程: 首先控制器接收使用者的請求,並決定應該呼叫哪個模型來進行處理,然後模型用業務邏輯來處理使用者的請求並返

PHP 單例模式例項解析

一、什麼是單例模式? 1、含義 作為物件的建立模式,單例模式確保某一個類只有一個例項,而且自行例項化並向整個系統全域性地提供這個例項。它不會建立例項副本,而是會向單例類內部儲存的例項返回一個引用。 2、單例模式的三個要點: (1). 需要一個儲存類