摘要:ASP.NET MVVM
MVVM是Model-View-ViewModel的縮寫
基本上也是一種程式系統分層的架構:
Model負責資料。
View負責呈現介面。
ViewModel則是前兩者間互動的媒介。
介面不能直接驅動資料,必須由ViewModel負責
詳細相關介紹可以閱讀這篇文章
http://blog.sanc.idv.tw/2011/12/wpf-mvvm.html
在ASP.NET MVVM裡面Excalibur將透過利用ASP.NET的Expression語法讓Web Form同樣做出類似WPF MVVM的架構,先來一個示範,請看看囉
1.首先網站的web.config要加進Excalibur的設定,註冊好'Binding'這個Expression語法需交由Excalibur的類別處理,(當然Bin裡面dll等等,那些也要放進去)
<system.web>
<compilation debug="true" targetFramework="4.0">
<expressionBuilders>
<add expressionPrefix="Binding" type="Extensions.Web.ViewModel.BindingExpressionBuilder"/>
</expressionBuilders>
</compilation>
</system.web>
然後我們做一個示範功能好了,只要一個網頁上有一個文字方塊與按鈕,可以輸入名子按下按鈕後在文字方塊下方,顯示輸入的名子即可,像下面這樣
2.在方案總管加入新項目Default.aspx至網站中,然後於設計的原始檔中加入各一個TextBox、Button、Label,調整並加入Binding語法如下
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>MVVM By ID</title>
</head>
<body>
<form id="form1" runat="server">
<div>
請輸入您的大名:<asp:TextBox ID="TextBox1" runat="server" Text="<%$ Binding: Name %>"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="確定" OnClick="<%$ Binding: Button1_Click %>" /><br />
<br />
<asp:Label ID="Label1" runat="server" Text="<%$ Binding: Text %>"></asp:Label>
</div>
</form>
</body>
</html>
這樣就幾乎完成MVVM其中的View了,要改變做法的是使用Binding,Binding裡面的文字意思就是View要繫結到ViewModel中的屬性名稱,而且這邊就連像OnClick這樣的event也可以透過Binding去繫結ViewModel裡面的method了,所以,至於Default.aspx.cs中的程式就一行都不需要去動它了,因為View不做其他事情
3.接下來要製作ViewModel的部分,在方案總管加入新項目Hello.ascx至網站中,因為示範的功能很小Model的部分就先用一個Label控制項來充當省略囉,Hello.ascx設計如下
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="Hello.ascx.cs" Inherits="ViewModel_Hello" %>
<asp:Label ID="Model" runat="server" Visible="false"></asp:Label>
4.撰寫Hello.ascx.cs的內容,分別完成Name屬性與Button1_Click方法中的程式,如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class ViewModel_Hello : System.Web.UI.UserControl
{
public string Name
{
get
{
return (ViewState["Name"] != null) ? ViewState["Name"].ToString() : "";
}
set
{
ViewState["Name"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
if (Name != "")
{
Model.Text = Name + ",您好。";
}
else
{
Model.Text = "請輸入名字";
}
}
}
到這裡一定要說明Hello.ascx的兩個地方:
(1)為何Label的ID屬性要設為'Model'?
答:是因為要有簡單的方式當做MVVM架構中Model物件的識別,或者如果有其他需求也有另一個方法可以在程式中實做IViewModel介面,指派其他或者不是控制項的物件做為Model。所以另外同樣的在View中也是用相同的規則,會用ID為ViewModel的控制項或實做IView介面,後指派的結果讓MVVM架構識別ViewModel物件
(2)為何View裡面Binding的Text屬性不用實做出來?
答:這是因為使用了幫ViewModel節省程式碼的機制,屬性名稱相同ViewModel就不用另外去寫轉譯Model的屬性到ViewModel上的程式,因為在View上Binding的規則是,如果ViewModel沒有這個屬性就允許透過去Binding裡面Model的屬性,因此只要屬性不是Binding在雙向的目標上,只是要唯讀呈現就可使用,否則不建議喔
5.最後終於要將ViewModel跟View結合起來了,到Default.aspx的設計頁面將Hello.ascx自方案總管拖曳進來,然後修改控制項ID為ViewModel,如下,建置成功,就完成囉
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ Register Src="ViewModel/Hello.ascx" TagName="Hello" TagPrefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>MVVM By ID</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:Hello ID="ViewModel" runat="server" />
請輸入您的大名:<asp:TextBox ID="TextBox1" runat="server" Text="<%$ Binding: Name %>"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="確定" OnClick="<%$ Binding: Button1_Click %>" /><br />
<br />
<asp:Label ID="Label1" runat="server" Text="<%$ Binding: Text %>"></asp:Label>
</div>
</form>
</body>
</html>
Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
詳細範例與程式碼下載連結於公告文章(Download)中