ASP.NET MVC4 IN ACTION學習筆記-第二波



ASPNET MVC4 視圖基礎(Views fundamentals)

--忽然發現我的時間不夠了,但是我還是完成了

image原著:ASP.NET MVC 4 IN ACTION

本人能力有限,盡量將書中的知識濃縮去講,仔細學過后,然后你再學習其他語言的MVC框架也就大同小異了

本次覆蓋知識點:

  1. 1. 把數據傳遞給視圖 (Providing data to the view )
  2. 2. 使用強類型視圖 (Using strongly typed views)
  3. 3. 使用視圖助手對象 (Understanding view helper objects)
  4. 4. 用模版 (Developing with templates)

 


 

      視圖(Views)是ASP.NET MVC 應用程序起決定性的一部分--它提供了一個很簡潔的方式,在你的應用程序中,邏輯中涉及到展現頁面的部分分離出來了。在上一章中的我們的Guestbook應用程序中,我們用Razor模版引擎寫了一些簡單的視圖,稍微了解了一點,最后,我們學習了layouts是如何讓你的應用程序中的所有頁面保持一致的風格,結束了上章的課程。

沒有學過的,上章飛機票:

      在本章中,我們將再稍微深入學習一下視圖---我們將會研究一下ASP.NET MVC如何呈現視圖,然后我們再看下把數據傳給視圖的其他不同的一些方法。最后,我們再講一下原來在 ASP.NET MVC 2 中介紹過的一些模版(temlate)特征,為了分析講解這些特征,我們一開始就會在我們的Guestbook應用程序中添加一個編輯頁面。

3.1  視圖介紹

    視圖的職責看似簡單。它的目標是與相對應的模型(Model)相關聯,並使用對應的模型來呈現內容。由於控制器(Controller)和相關聯的服務已經處理了所有的業務邏輯,並且把處理后的結果封裝成了模型對象,而視圖只需要知道怎樣把這個模型轉換成HTML來呈現就行了。

   盡管這種職責關系的分離可能,對傳統的ASP.NET應用程序編程人員來說編寫造成了麻煩和困擾,但是視圖你還是要編寫的。為了保證你的視圖不會太復雜而很難去維護,所以對於視圖,你還是要小心仔細的,要有意的去設計它.

   在我們學習“如何把數據傳遞給視圖”的方法之前,我們先研究一下MVC框架是怎樣把視圖給呈現的。

 

   3.1.1 選擇一個視圖去展示

     在上一章里面我們通過調用一個控制器里面的一個action中的一個View方法來讓頁面呈現了。下面這個是我們的GuestbookController控制器里的Create操作:

     image

   通過這些代碼, Views/Guestbook/Create.csthml 這個視圖文件就會被呈現。但是在這個應用程序中,MVC框架怎么知道去呈現這個指定的視圖,而不是其他視圖,比如說Index.cshtml的呢?

   調用View方法將會返回一個 知道怎么去呈現指定的視圖的ViewResult對象。當調用View的無參數方法時,MVC框架就會認為你要呈現的視圖的名字跟這個方法所在的action(Create)名字一樣。之后,MVC框架的ControllerActionInvoker類就會去調用ViewResult類,然后把呈現頁面的責任轉交給了它。在這個時候,這個框架也會命令ViewEngineCollection去查找要呈現的頁面的位置。(回顧一下上一章的內容。這個視圖引擎默認會在 Views/<Controller Name>目錄和Views/Shared目錄)

   視圖引擎

    不同的視圖引擎會有它不同的格式去呈現視圖,默認 ASP.NET MVC有兩個視圖引擎-RazorViewEngine和WebFormViewEngine。Razor視圖引擎的格式是cshtml文件或者vbhtml文件,然而WebForm視圖引擎依舊支持老格式的Web Form視圖(aspx頁面和.ascx文件)。以前的ASP.NET MVC版本默認都只包括WebForm視圖引擎。

    為什么在ASP.NET MVC3中要引入新的視圖引擎呢?隨着ASP.NET 1.0的發行的開始,Web Form就允許把代碼和標簽寫在一個aspx頁面里面,但是把C#代碼寫在aspx頁面里面,控件的邏輯寫法在通常的開發中嚴重受到阻礙。取而代之的是,開發者們努力去把所有的邏輯放在了頁面的后面(代碼后置)。隨着ASP.NET 的發布,在aspx文件中增加了數據綁定,其他更新的模塊都去適應配合控件開發的模式。

    在許多MVC的框架里,視圖開發都鼓勵和要求代碼,直接用標簽去寫(也就是不用控件),由於ASPX視圖引擎在設計時沒有達到這個目標,所以ASP.NET團隊決定去設計一個全新的視圖引擎--把代碼寫在模版里的一種模式。這是一種更智能的引擎,引擎能夠很容易地識別出標簽的開始和結束,而且開發者也不用寫的那么復雜。

當然你也可以用別的第三方的視圖引擎,在第10章,我們就會去看一下現在比較流行的Spark視圖引擎。

   3.1.1 重寫View

      如果你不想你的視圖名字跟action一樣。你可以使用View的重載方法。例如

     return View("New");   查找路徑 Views/<Controller Name>/New.cshtml和Views/Shared目錄,而不再是action的名字了

     你還可以寫路徑,就可以脫離默認的控制名了的路徑限制了

     return View(("~/Views/SomeOtherDirectory/New.cshtml");

   3.1.2 把數據傳給視圖

      我們還是在我們的Guestbook案例上繼續編寫。上篇代碼案例

     我們將要講一下把數據傳給視圖的3種不同的方法---ViewDataDictionary,ViewBag,強類型視圖

   3.2.1 ViewDataDictionary

      把數據傳遞給視圖過去經常使用的最主要的對象就是ViewDataDictionary

     和其他MVC框架一樣,ASP.NET MVC也暴露一個集合:可以把更多的model對象傳遞給視圖使用,然后視圖可以利用model里面封裝好的信息來展示信息。

     比如說,我們可以拓展我們的guestbook頁面---所有人都可以查看guestbook,但是只有當前登錄的用戶可以編輯guestbook entries(guestbook中的一個實體對象,也就是一條記錄)。為了可以達到這個目的,我們可以通過GuestbookEntry對象,代碼如下:

     image

    盡管,這個GuestbookEntry類已經包括了所有我們要在使用GuestbookEntry的頁面上展示的數據了,但是它不包括當前登錄的用戶的信息,或者不能決定視圖是否顯示Edit超鏈接。我們需要給視圖更多的信息,不能僅僅靠GuestbookEntry來做這個決定。我們可以使用ViewDataDictionary來提供更多的信息,代碼如下

public ActionResult Show(int id) {
            var entry = _db.Entries.Find(id);  //找到該Id的Entries
            bool hasPermission = User.Identity.Name == entry.name; //如果登陸人的姓名等於entry錄入人的姓名,就顯示Edit按鈕
            ViewData["hasPermission"] = hasPermission;
            return View(entry);
        }

添加到Controllers/GuestbookController.cs這個文件里面

imageimage

在Controller里面我們可以直接使用ViewData,因為Controller繼承ControllerBase類,ControllerBase下面有ViewData屬性。我們通過比較GuestbookEntry的name和當前登錄用戶的name是否一樣,然后比較結果放在hasPermission里面,然后視圖那邊查看hasPermission是true還是false來決定是否顯示Edit超鏈接。

添加Show視圖,右鍵action名稱,添加視圖,然后直接點添加

image

視圖里面代碼如下:

@{
    ViewBag.Title = "Show";
}
 
<p>
    @{
        bool hasPermission = (bool)ViewData["hasPermission"];
    }
    @if (hasPermission)
    { 
        @Html.ActionLink("Edit", "Edit", new { id = Model.Id });
    }
    @Html.ActionLink("返回 Entries","Index")
</p>
 
 

現在我們來運行我們的項目:如果是從我的csdn上下載的,默認里面有3條數據了。

運行的時候,我們手動在地址欄的后面輸入Guestbook/Show/1,其中1是entry的id號,在controller里面我們不是留了一個參數嗎?在Asp.NET MVC中,你可以這樣傳遞參數,完整模擬路徑如下

http://localhost:端口號/Guestbook/Show/1

跳轉后,頁面默認如下:因為你還沒有登錄,所以不會顯示Edit超鏈接

數據庫中的表數據一覽,目前id只有1,2,3,所以測試的時候,不要輸入其他的

image

 

①輸入地址后,顯示效果如下

image

測試我們先注冊一個用戶,名字叫 茗洋芳竹,密碼叫123456

image

注冊好了,會自動登陸

image

輸入Show/2,因為id=2的信息是  name等於茗洋芳竹,是本人,所以顯示了Edit超鏈接

 

 image
 

我猜想,如果你以前做過WebForm的話,聰明的你肯定已經領悟出來什么了.

 

3.2.2 ViewBag

    ViewDataDictionary一樣,ViewBag也是把數據傳遞給視圖使用的一種手段.ViewBag使用了C#4.0中的 的dynamic語法.

它不是使用key字符串在集合里存儲對象了,你可以在你的controller中簡單的設置一下dynamic類型的ViewBag的一個屬性.

image

hasPermission是ViewBag的一個根本不存在的屬性,這里名字隨便取,因為ViewBag是個dynamic類型的.不懂dynamic的可以查看一下C# dynamic資料

如果采用ViewBag的方式

那么Show頁面稍微改下就行了

原本代碼是這樣的image

 

bool那里面的代碼可以不要了,if后面的那個條件,直接改成

image

就行了.

估計ViewBag你已經會用了,Model從哪里來的,你先不用管,估計你也猜到了,我們在Controller中調用View()方法的時候,加了一個實體對象作為參數.那么這里你就可以用Model來等效於你后台傳來的實體對象那樣使用就行了.

盡管ViewData和ViewBag的都為解決數據傳遞視圖的問題而提供了很多的靈活性,但是也因此付出了很大的代價.如果你偶爾把一個dynamic屬性名稱敲寫錯了,編譯的時候是找不到錯誤的,這些技術所以也有不友好的地方.除此之外,在Visual Studio中 dynamic的屬性,編寫代碼時候是沒有提示的,ViewData也沒有,你要記得ViewData中的鍵名稱。(盡管有第三方企業工具:比如說JetBrains ReSharper可以支持它)

 

除此之外,你也不能很容易地在dynamic屬性上綁定元數據.而在ASP.NET MVC框架里面,你可以利用特性的優勢,直接把元數據綁定到現在比較常用的類型上(比如說,在System.ComponentModel.DataAnnotations命名空間下的驗證特性,你可以用來標記一個字段是否不能為空(required),一個字段的長度限制等等),這些特性在dynamic的ViewBag屬性上都是不能使用的

取而代之的是,你可以使用強類型視圖,一個使用了強類型類的視圖.通過這個方法,你就可以利用vs獲得智能感知和vs的的重構工具來高效快速的寫代碼了.你也可以用特性驅動元數據的方法獲得好處.在下一節我們來研究一下.

 

3.2.3 強類型視圖,一個視圖模型

 當你使用基於Razor的視圖的時候,你的視圖可以繼承兩種類型,默認的是System.Web.Mvc.WebViewPage或者System.Web.Mvc.WebViewPage<T>,WebViewPage<T>繼承WebViewPage,所以提供了一些WebViewPage沒有的一些特征.

  下面是 WebViewPage<T>內部骨架(Skeleton)的一些定義

image

 

  除了提供了強類型的ViewData.Model的包裝,然后你就可以使用Model外,WebViewPage<T>還提供了兩個可以在視圖中可以使用的AjaxHelper和HtmlHelper對象.

   為了使用強類型視圖,首先你要在你的Controller的action中設置ViewData.Model屬性,在Listing 3.4中,我們查出了所有的guestbook entries,然后展示在列表頁面上,在View方法中我們傳遞了一個實體.換句話說,也就是換個形式封裝設置了ViewData.Model屬性了,所以你在視圖頁面就可以直接使用Model屬性了.

image

 

我們修改GuestbookController中的Index操作和相對應的視圖頁面(Guestbook/Index.cshtml)

image

 在Index視圖上就是用這個Action的.即使是一個弱類型的WebViewPage類,但是也可以使用ViewData.Model屬性的.但是這個屬性是一個類型對象,我們需要轉換一下結果才能有效的使用.取而代之,我們可以使用@model關鍵字來使我們的父類WebViewPage<T>指定model類型

  • @using GuestInfo.Models
  • @model List<GuestbookEntry>

通過使用@model關鍵字我們指定了model的類型,現在我們的視圖已經繼承了於WebViewPage<T>而不是WebViewPage了.現在我們已經有了一個強類型的視圖了.我們也可以使用@using關鍵字導入命名空間.在下一節里,我們將要看一下,在一個視圖里我們怎樣使用model對象來展示信息.

image

3.2.4 在一個視圖里面展示視圖model的數據

        在一個視圖里面展示信息,通常的,你可能使用HtmlHelper對象去輔助讓這個model生成html,思考一下下面一個展示了一個完整的Guestbook entry信息的代碼,這個代碼寫在Views/Guestbook/Show.cshtml

<h2>Guestbook Entry</h2>
<dl>
    <dt>姓名:</dt>
    <dd>@Model.Name</dd>
    <dt>日期:</dt>
    <dd>@Model.DateAdded</dd>
    <dt>消息:</dt>
    <dd>@Model.Message</dd>
</dl>
<p>
    @{
        bool hasPermission = (bool)ViewData["hasPermission"];
 
    }
    @if (ViewBag.hasPermission) //       ViewBag.hasPermission
    { 
        @Html.ActionLink("Edit", "Edit", new { id = Model.Id });
    }
    @Html.ActionLink("返回 Entries", "Index")
</p>

上面這段代碼我相信你們應該能看懂了.看不懂的,在評價里面說一下

當我們在屏幕上展示未編碼的用戶輸入的信息的時候,我們寧可不留出存在多種腳本攻擊的可能性.還好這個數據在呈現於屏幕之前已經自動編碼了.如果你想展示一個沒有編碼過的文本,你可以使用Html.Raw方法來使那些信息以純文本的形式展現.

 

 

在login頁面里面,我們使用一個視圖model對象來表達了一個表單的全部的數據,代碼如下

image

這個登陸頁面也非常簡單,如下

 

image

 

由於在Log on屏幕里,我們選擇一個強類型視圖,我們使用了內置的助手去幫助為每一個節點生成html.為了替換掉使用弱綁定來呈現action的參數,我們可以使用基於表達式的HtmlHelper拓展來創建不同類型的input節點,代碼如下(Views/Accout/register.cshtml)

@model GuestInfo.Models.RegisterModel
@{
    ViewBag.Title = "注冊";
}
 
<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
    <h2>創建新帳戶。</h2>
</hgroup>
 
@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()
 
    <fieldset>
        <legend>注冊表單</legend>
        <ol>
            <li>
                @Html.LabelFor(m => m.UserName)
                @Html.TextBoxFor(m => m.UserName)
            </li>
            <li>
                @Html.LabelFor(m => m.Password)
                @Html.PasswordFor(m => m.Password)
            </li>
            <li>
                @Html.LabelFor(m => m.ConfirmPassword)
                @Html.PasswordFor(m => m.ConfirmPassword)
            </li>
        </ol>
        <input type="submit" value="注冊" />
    </fieldset>
}
 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

 

其中這段代碼image

功能類似於

<label for=”UserName”>姓名</label>

<input id=”UserName” name=”UserName” type=”text” value=”” />

由於這個label和input都可以用表達式(expression)來生成,所以我們不用再記復雜的label和input名稱了

HtmlHelper被設計時就支持強類型視圖

image

由於我們的表單都是使用強類型視圖生成的,所以我們在controller中可以好好設計action,讓這個表單可以post提交上去.

而不是列舉每一個input字段作為一個action方法的參數,我們可以綁定所有的參數給同一個view model(我們曾經想要展現的視圖)

image

在這里可以有兩個參數,當然你也可以有多個.這里你也看到了,這里有個returnUrl,而不是表單中input節點.第一個參數,是一個model,封裝好了所有input中的值

隨着HtmlHelper對強類型視圖支持的越來越好,如果你只是僅僅依靠這些拓展來生成HTML,那么在你的視圖里面就會有一些重復.舉個例子,如果每個input節點都想要一個對應的label,那么為什么不能包括它呢?每一個用戶接口都是不一樣的.ASP.NET MVC團隊不能猜對每個使用的input和label的布局的人想要什么樣的布局(layout).雖然每一個input節點都應該有有個label.但是這個現存的helper方法可以創建那些不需要label的input節點.相反的,我們可以使用ASP.NET MVC2中的特征的優點--模版--去掌握一個更標准化的html的生成方式

 

 

3.2.4 使用強類型模版

     如果你現在已經轉向用基於表現層的model形式的強類型視圖模式開發,那么你將要開始發現越來越多的句式出現了。如果你的表現層model對象在表單里有個boolean屬性,你肯定會去使用checkbox在表單里面呈現。Email地址,password字段等等都是的。input節點沒有對應的驗證信息是很少出現的。

      除了使用HtmlHelper以外,在ASP.NET MVC2開始出現的時候,templated helpers新的特性出現了,它被設計基於強類型視圖用來輔助設計生成html的一個技術。Templated helper可以為一個完整的model生成html或者為一個member生成html。

  

3.3.1 EditFor和DisplayFor 模版

    這兩個不同的模版集被分成了編輯(editor)和展現(display)模版。這個編輯和展現的模版有下面代碼生成

image

  雖然在使用模版,同樣效果用字符串方式的方法對弱類型的視圖不利,但是我們可以使用基於表達式的方法來在強類型視圖里面獲得優勢(lambda表達式語法)。如果我們的model比較簡單,我們可以使用ForModel系列的方法,它會重復遍歷model中的每一個成員(

member),然后生成html。

  在我們的修改密碼的頁面上布局比較簡單,我們可以使用EditorForModel方法來生成一個用於編輯信息的表單

 

  ①我們在Models/AccountModels.cs里面我們先添加一個類

    image

這個代碼和LocalPasswordModel代碼一樣的,我們復制一下代碼改一下名字。

雖然已經有了更改密碼的頁面了,但是這里我們只是練習一下EditorForModel的用法,還希望不用嫌麻煩

接下來我們在Controller/AccountController.cs用法

添加一個Action

  public ActionResult ChangePasswordPage() {
            ChangePasswordModel newPassword = new ChangePasswordModel();
            return View(newPassword);
        }
 
接下來我們右鍵該action名字,添加一個視圖。
視圖代碼如下:
@{
    ViewBag.Title = "ChangePasswordPage";
}
@using (Html.BeginForm())
{ 
  <div>
      <fieldset>
          <legend>用戶信息</legend>
          @Html.EditorForModel();
          <p><input type="submit" value="改變密碼"/></p>
      </fieldset>
 
  </div>  
}
 
 
接下來按F5運行,可能首先你要登陸一下
 
登陸:
image
 
登陸成功后,我們先看一下原配的,點擊一下你的名字,進入更改密碼界面
image
image
 
接下來我們修改一下地址欄
image
 
EditorForModel方法會在所在的view上循環對應model中所有的member(成員),會為每個成員生成editor模版,我自己覺得這個也不怎么常用吧。文本框上面的文字,來自ChangePasswordModel類
image
 
 
但是有時,我們不可能只要這么簡單的輸出html,為了更靈活,比如說我們調整布局,或者添加更多的html標簽等等
接下來我們使用EditorFor模版
image效果如下,發現只有含有驗證功能的文本框
 
image
 
當然,你把EditorFor改成Editor也行,只不過有的名稱你可能記不住,所以說For系列的模版,例如EditorFor而不是Editor,所以正確性更高
代碼如下
image
 
 
3.3.2 內置模版
 不出所料,ASP.NET MVC有一套自己的編輯和展示的模版,大致如下
    image
 
 
除了Collection和Object模版,其他的模版都呈現的是唯一的值,Object模版循環訪問ModelMetadata.Properties集合中的每一項,每一項展現的時候都調用對應的display模版.Collection模版循環訪問model對象中的每一項,並為列表中的每一項調用對應的display模版顯示。
正如你預料到的,展示模版在瀏覽器中呈現為一個節點,例如純文本或者一個錨標簽,相反地,editor(編輯)模版展現的是表單中的節點,默認的編輯模版在表3.3都列出來了
image
 

3.3.3 查找模版

editor模版和display模版助手方法(helper methods)都是通過名字查找對應的模版.模版的名字的值也是有來源的.模版助手方法根據這個名字,然后用明確的算法找到對應的模版並呈現。一旦匹配找到了,就會立即去呈現內容。 模版助手方法在根據下一個模版名字查找之前,會根據明確的路徑查找模版。查找的路徑是EditorTemplates和DisplayTemplates文件夾。跟控制器找視圖有點像.如果一個助手方法在一個明確域(area)的視圖里面被使用了,被查找的文件夾可能是:
 
<Area>/<ControllerName>/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml) <Area>/Shared/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml)
 
如果模版不在這些文件夾里,或者視圖不在域里,這個默認的視圖查詢地址就會被使用
 
<ControllerName>/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml) Shared/EditorTemplates/<TemplateName>.cshtml(或者.vbhtml)
  •  
  • 關於模版的查找是遵循算法的
  • image
 
舉個例子:

我們現在要在更改密碼頁面上展現一個自定義的ChangePasswordModel模版。model我們已經有了,現在我們只需要定義一個更model類型名字(ChangePasswordModel)一樣的模版就行了。文件放的路徑如下圖

imageimage

左邊一個,只給AccountController使用,右邊一個,所有的控制器都可以使用,EditorTemplates文件夾是自己建立的

 
 
3.3.4 自定義模版(難)
 
總而言之,有兩種理由去創建一個自定義模版

■ 創建一個自定義模版 ■ 重寫現有的模版

 
首先我們看一下在控制器明確的視圖文件夾下的模版解決方案規則,因此我們能夠很明確的在Shared文件夾下重寫一個內置的模版,然后我們在重寫控制器明確的視圖文件夾里。
解釋一下“控制器明確的視圖文件夾”:例如GuestController這個就是控制器明確了,名字是Guest,所以我們能找到對應的視圖文件夾,例如 Views/Guest/…   這個最終的文件夾路徑就是  控制器明確的視圖文件夾
打個比方,你可能有一個應用廣泛的模板,用於顯示的電子郵件地址.然后在一個域或者控制器模版的文件里提供一個模版。
在大多數情況下,模版跟創建一個類型是一樣的。ChangePasswordModel模版標簽如下
image
 
創建一個新的Object.cshtml.里面用了EditorFor模版,每一個被P標簽包裹。局部模版有什么好處?
首先,局部模版在視圖里面都是通過名稱找到的。避開在視圖中明確指定哪一個模版被調用的需要,模版可以從model元數據信息中找到。此外模版能夠在ViewDataDirectory中獲得額外的信息,然而局部模版和其他的頁面是獲得不到的。這些信息在View.Data.ModelMetadata屬性中.只有在ASP.NET MVC中模版才有ModelMetadata屬性.在局部模版和視圖,這些屬性都為null
使用ModelMetadata屬性時候,你能夠獲得從model元數據提供器生成的所有元數據信息。這些包括關於model的model類型信息,屬性,和元數據。
Model類型信息包括的屬性都在表3.4列出來了
image
 
除了一些model類型信息之外,ModelMetadata也包含了其他的metadata,默認的都是來自特性.如圖表3.5
image
 
在我們自定義模版中,我們研究一下這些model元數據,然后去自定義HTML去呈現。除了在表3.4和3.5列出來的屬性之外,ModelMetadata對象暴露了一個IDictory<string,object>類型的AdditionValues屬性。這個屬性包含了一些來自自定義model元數據提供者的額外的元數據信息.舉個例子:如果你想展示一個必填的(required)字段,我們只需要在我們的自定義模版中檢測這個IsRequired屬性。比如說我們要裝飾一下我們的實體中的一個DataType.DateTime數據類型的特性,我們可以用一個日期捕獲插件來自定義個模版來呈現時間。
實踐一下,我們可能要重寫一下現有的模版,因為這個現有的Object模版可能適合,可能不適合我們的需求。這個model的元數據不能包括任何樣式信息,所以自定義的樣式和其他的標簽都是通過重寫內置的模版完成的。但是很多網站都趨向於標准的通用的用戶接口布局,比如說我們通常把一個label放在一個input上面用作標記和提醒用戶,或者用一個*來標記這個input是必須輸入內容的。我們只需要重寫模版,就可以潛移默化地影響整個站點。

比如說,我們可能希望把label放在跟input放在同一行,而不是在一列后右對齊,為了達到這個目的,我們需要重寫現有的Object模版

①我們首先在 Views/Shared/下面建立一個EditorTemplates文件夾,添加一個Object.cshtml,代碼如下
@foreach (var prop in ViewData.ModelMetadata.Properties
                  .Where(pm => pm.ShowForEdit
                       && !ViewData.TemplateInfo.Visited(pm)))
{ 
    <div class="editor-field-container" style="clear:both">
        @if (!String.IsNullOrEmpty(
                    Html.Label(prop.PropertyName).ToHtmlString()))
        { 
            <div class="editor-label  float-left">
                @Html.Label(prop.PropertyName)                 
            </div> 
        }
        <div class="editor-field float-left">
            @Html.Editor(prop.PropertyName)
            @Html.ValidationMessage(prop.PropertyName, "*")
        </div>
        <div class="cleaner" style="clear:both"></div>
    </div> 
  
}

②接下來修改Views/Account/Login.cshtml代碼

@model GuestInfo.Models.LoginModel
 
@{
    ViewBag.Title = "登錄";
}
 
<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
</hgroup>
 
<section id="loginForm">
<h2>使用本地帳戶登錄。</h2>
@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
 
    <fieldset>
        <legend>“登錄”表單</legend>
        @Html.EditorForModel()
 
        <input type="submit" value="登錄" />
    </fieldset>
    <p>
        @Html.ActionLink("Register", "Register") (如果你沒有帳戶)。
    </p>
}
</section>
 
<section class="social" id="socialLoginForm">
    <h2>使用其他服務登錄。</h2>
    @Html.Action("ExternalLoginsList", new { ReturnUrl = ViewBag.ReturnUrl })
</section>
 
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

按F5運行效果,登陸頁面如下:

image

 

我們創建了一個foreach循環,一層一層地遍歷了在編輯時以前應該顯示的或者不應該顯示的ModelMetadata.Properties屬性.展示一個label,editor模版,還有驗證信息,把每一個屬性放在一個div標簽里面.最后我們包括了一個cleaner div重置了浮動樣式應用於實現列布局.這個最終效果在圖3.5
在一個全局的模版中通過放一個普通的呈現邏輯,我們可以很容易的跨站點為我們的視圖,提供標准化display和editor布局.為了達需要自定義化的效果的域,我們要有選擇性的重寫或者提供一個新模版,通過在一個地方標准化和封裝我們的呈現內容的邏輯,我們在一個地方編寫了很少的代碼就影響了整個站點(site),如果我們想要改變我們的時間插件,我們可以簡單的寫一個data-time模版,就可以很容易改變我們的站點,讓它呈現不同的內容。

 

 

3.4 總結

MVC框架可以在視圖(頁面)里減少很多商業邏輯,不幸運的是,視圖給我們帶來了很多必須掌握的復雜的東西,為了應付這個復雜度和難點,為了提高視圖和其他模塊的結合性,我們研究了怎樣使用強類型視圖和隔離開的視圖model,隨着分離的視圖model的普遍增加,使用模版從這些視圖model中獲得元數據來呈現內容的概念已經成為可能。在分隔開的視圖model中,在你的應用程序中,我們還是要保持視圖和model是分離開的理念。
 現在我們理解了視圖是怎么工作的了,下一章我們將探討一下控制器基礎
 
 
第二章代碼下載:http://download.csdn.net/download/yangyanghaoran/5207734

 額外贈送:

臨時去除迅雷看看廣告的做法【原創】
①打開資源管理器

           


②打開迅雷看看,播放任意電影,緊接着會有廣告

          

 
        
    ③查看資源管理器,多了一個這個進程 XLUEOPS.exe,我們只要在廣告播放的30秒內手動 關閉此進程,就可以立即 去掉廣告,每次放廣告,迅雷看看都會加載此進程

         

        ④右鍵單擊它,結束進程,就可以臨時去掉廣告

其他方法:

    

如果你裝了360安全衛士,直接點一鍵加速,就可以臨時去掉廣告

 

 

 

 
        

個人覺得3.3.4 自定義模版有點難,看不懂的也不用糾結我。這里只是視圖基礎,具體的以后再講

 

關於ASP.NET MVC4 IN ACTION系列目錄地址已經生成:點擊查看目錄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM