[Excalibur]ASP.NET MVVM(1)

摘要: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)

 

ASP.NET MVVM(2)
ASP.NET MVVM(3)