閱讀目錄:
目前成都創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站托管運(yùn)營、企業(yè)網(wǎng)站設(shè)計、玉屏網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
7.HtmlHelper、HtmlHelper
8.控制ViewModel中的某個屬性的呈現(xiàn)(使用PartialView部分視圖細(xì)粒度控制ViewModel的呈現(xiàn))
9.模板的裝飾者模式(PartialView與ViewModel的嵌套使用(簡))
在View中用來根據(jù)當(dāng)前View中引入的強(qiáng)類型ViewModel生成HTMLDom結(jié)構(gòu)的核心功能都被封裝在以HtmlHelper為首的對象模型中,包括HtmlHelper
但是這兩個類型所能做的事情很有限,它們只是龐大生成功能的核心模型;我們使用的都是圍繞著這兩個類型的擴(kuò)展方法,如:
@Html.EditorForModel()
在當(dāng)前View中引用的Html屬性其實(shí)是一個HtmlHelper
public HtmlHelperHtml { get; set; }
該類型被定義在public abstract class WebViewPage
@model MvcApplication4.Models.Customer
正是這里泛型類型的類型參數(shù),所以圍繞著HtmlHelper
@Html.EditorFor(model => model.Shopping)
這意思是說在View中輸出一個編輯model.Shopping屬性的文本框HtmlDom結(jié)構(gòu),但是我們調(diào)用的明明是一個沒有任何類型形參的方法,其實(shí)它已經(jīng)通過上面說將的環(huán)節(jié)進(jìn)行了類型關(guān)聯(lián);
畫紅線的部分是View所使用的強(qiáng)類型HtmlHelper
public static class EditorExtensions { public static MvcHtmlString EditorFor(this HtmlHelper html, Expression > expression); }
上述代碼中加粗的部分正是關(guān)鍵所在,這里擴(kuò)展的其實(shí)是我們在View中引入的強(qiáng)類型參數(shù)的HtmlHelper<MvcApplication4.Models.Customer>,這樣任何圍繞HtmlHelper
對于ViewModel的呈現(xiàn)一直都是被系統(tǒng)控制著,雖然一個簡單的字符串類型字段可以用一個文本框的HtmlDom結(jié)構(gòu)方式呈現(xiàn)出來,但是那僅僅是代表著沒有任何業(yè)務(wù)概念的功能性設(shè)置,也就是出發(fā)點(diǎn)是從CLR類型系統(tǒng)考慮的,而不是特定領(lǐng)域角度;如果這個字符串代表著某種業(yè)務(wù)概念,那么我們希望通過更人性化的方式讓用戶使用,而不是一個硬生生的文本框;我們可能會需要提供了一個供自動輸入提示的HtmlDom結(jié)構(gòu),該結(jié)構(gòu)可能還需要其他的UI成員協(xié)助,如:自動提示可能需要JS、后臺Service接口等一系列成員相互協(xié)調(diào)完成;
這是一個簡單的需求,在大型項(xiàng)目中這樣的功能很常見,也是到處會使用到,不單單是一個兩個頁面,N多頁面都會有一點(diǎn)點(diǎn)的差異性,但是整體功能都會差不多,這樣我們只需要在設(shè)計的時候適當(dāng)?shù)奶峁┮恍┙涌诰涂梢粤耍?/p>
那么ASP.NETMVC是如何生成前臺所需要的HtmlDom結(jié)構(gòu)的呢?前面一章我們總結(jié)了,對于ViewModel的呈現(xiàn)形式只會有兩種,一種是Edit一種是Display,不會有其他的呈現(xiàn)形式,所以在圍繞著HtmlHelper對象的擴(kuò)展方法中大多數(shù)都是以這種類別區(qū)分的,Edit一組,Display一組;
到目前位置我們已經(jīng)知道ViewModel與View之間的橋梁是Model元數(shù)據(jù),可以簡單的理解為HtmlHelper
public class Address { [UIHint("CustomAddress")] [Display(Name = "地址")] public string AddressId { get; set; } }
我們在Address類型中為AddressId屬性加上一個UIHint類型的特性,其實(shí)意思是想說明我們在程序內(nèi)部使用的是使用地址ID,而在現(xiàn)實(shí)的時候我們希望將原來很單調(diào)的地址ID編程一個更人性化的地址顯示方式,比如:位于什么省、什么市等等一些其他的地理信息;
在ASP.NETMVC內(nèi)部有一個internal static class TemplateHelpers 類型的模板輔助類,該類是大部分模板化輸出的幫助接口,在該類的內(nèi)部定義了一套模板化使用的字典:
視圖的類型:
static readonly DictionarymodeViewPaths = new Dictionary { { DataBoundControlMode.ReadOnly, "DisplayTemplates" }, { DataBoundControlMode.Edit, "EditorTemplates" } };
這里定義了兩組類型,也就是顯示、編輯,這兩組類型將作為查找自定義模板的物理文件夾路徑,同樣ModelMedata中的同一個屬性在不同的顯示類型中將有不同的判斷作用;
編輯、顯示:
static readonly Dictionary> defaultDisplayActions = new Dictionary >(StringComparer.OrdinalIgnoreCase) { { "EmailAddress", DefaultDisplayTemplates.EmailAddressTemplate }, { "HiddenInput", DefaultDisplayTemplates.HiddenInputTemplate }, { "Html", DefaultDisplayTemplates.HtmlTemplate }, { "Text", DefaultDisplayTemplates.StringTemplate }, { "Url", DefaultDisplayTemplates.UrlTemplate }, { "Collection", DefaultDisplayTemplates.CollectionTemplate }, { typeof(bool).Name, DefaultDisplayTemplates.BooleanTemplate }, { typeof(decimal).Name, DefaultDisplayTemplates.DecimalTemplate }, { typeof(string).Name, DefaultDisplayTemplates.StringTemplate }, { typeof(object).Name, DefaultDisplayTemplates.ObjectTemplate }, }; static readonly Dictionary > defaultEditorActions = new Dictionary >(StringComparer.OrdinalIgnoreCase) { { "HiddenInput", DefaultEditorTemplates.HiddenInputTemplate }, { "MultilineText", DefaultEditorTemplates.MultilineTextTemplate }, { "Password", DefaultEditorTemplates.PasswordTemplate }, { "Text", DefaultEditorTemplates.StringTemplate }, { "Collection", DefaultEditorTemplates.CollectionTemplate }, { typeof(bool).Name, DefaultEditorTemplates.BooleanTemplate }, { typeof(decimal).Name, DefaultEditorTemplates.DecimalTemplate }, { typeof(string).Name, DefaultEditorTemplates.StringTemplate }, { typeof(object).Name, DefaultEditorTemplates.ObjectTemplate }, };
這是兩組顯示模式的模板化操作方法的字典,可以看出同一個HiddenInput特性將在不同的顯示模式先輸出不同的HtmlDom結(jié)構(gòu);
在我們的ASP.NETMVC項(xiàng)目中要同樣的有兩組文件夾DisplayTemplates、EditorTemplates,這兩個文件夾將會是系統(tǒng)查找的路徑;
我們在DisplayTemplates目錄下創(chuàng)建了一個用來顯示客戶地址信息的自定義模板,其實(shí)也就是PartialView部分視圖,用來重用UI;在該部分視圖中,我們寫點(diǎn)測試數(shù)據(jù):
@model string@Model
地址:上海市、長寧區(qū)
氣溫:-1~10
交通:方便出行
然后我們刷新一下界面,看如何個性化了地址顯示;
這樣我們就可以控制細(xì)粒度的ViewModel顯示;
其實(shí)我們應(yīng)該能夠領(lǐng)悟到通過PartialView與HtmlHelper彼此互相嵌套能讓原本單一的部分視圖變成一個強(qiáng)大的具有設(shè)計模式功能的模板裝飾者模式;想想看,如果我們將這里的AddressId類型再設(shè)計成復(fù)雜的類型,然后在該復(fù)雜的類型內(nèi)部我們嵌套了一個原本在其他地方使用的地址類型ViewModel,而且剛好該類型也具有相應(yīng)的部分是視圖,這樣我們就可以將ViewModel的嵌套使用與PartialView嵌套使用相結(jié)合,這樣就可以使用類似設(shè)計模式中的裝飾者模式來完成很多UI上的展現(xiàn)重用功能;
作者:王清培
出處:http://wangqingpei557.blog.51cto.com/
本文版權(quán)歸作者和51CTO共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。