閱讀目錄:
目前成都創(chuàng)新互聯(lián)已為1000+的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)絡(luò)空間、網(wǎng)站托管運(yùn)營(yíng)、企業(yè)網(wǎng)站設(shè)計(jì)、玉屏網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長(zhǎng),共同發(fā)展。
7.HtmlHelper、HtmlHelper<T>中的ViewModel的類型推斷
8.控制ViewModel中的某個(gè)屬性的呈現(xiàn)(使用PartialView部分視圖細(xì)粒度控制ViewModel的呈現(xiàn))
9.模板的裝飾者模式(PartialView與ViewModel的嵌套使用(簡(jiǎn)))
在View中用來(lái)根據(jù)當(dāng)前View中引入的強(qiáng)類型ViewModel生成HTMLDom結(jié)構(gòu)的核心功能都被封裝在以HtmlHelper為首的對(duì)象模型中,包括HtmlHelper<T>泛型類型,它直接派生自HtmlHelper基類,這兩個(gè)類型的功能都是圍繞著如何生成前端所需要的HTML結(jié)構(gòu)和一些常用的UI元素;
但是這兩個(gè)類型所能做的事情很有限,它們只是龐大生成功能的核心模型;我們使用的都是圍繞著這兩個(gè)類型的擴(kuò)展方法,如:
@Html.EditorForModel()
在當(dāng)前View中引用的Html屬性其實(shí)是一個(gè)HtmlHelper<T>類型的屬性,定義代碼:
public HtmlHelper<TModel> Html { get; set; }
該類型被定義在public abstract class WebViewPage<TModel> : WebViewPage類中,其實(shí)該類是一個(gè)模板化代碼生成的基類;我們?cè)贏SP.NETMVC項(xiàng)目中添加的所有View文件都會(huì)直接或間接的繼承自該類型,在View中引入的類型定義:
@model MvcApplication4.Models.Customer
正是這里泛型類型的類型參數(shù),所以圍繞著HtmlHelper<T>的擴(kuò)展方法才變成靈活的泛型的代碼生成接口;因?yàn)樗麄儽舜送ㄟ^(guò)強(qiáng)大的泛型類型推斷,依次的推斷下去,最終會(huì)到達(dá)擴(kuò)展方法的內(nèi)部,如:
@Html.EditorFor(model => model.Shopping)
這意思是說(shuō)在View中輸出一個(gè)編輯model.Shopping屬性的文本框HtmlDom結(jié)構(gòu),但是我們調(diào)用的明明是一個(gè)沒(méi)有任何類型形參的方法,其實(shí)它已經(jīng)通過(guò)上面說(shuō)將的環(huán)節(jié)進(jìn)行了類型關(guān)聯(lián);
畫(huà)紅線的部分是View所使用的強(qiáng)類型HtmlHelper<T>對(duì)象,類型參數(shù)是我們?cè)赩iew中通過(guò)@model的方式定義的;畫(huà)綠色的部分也是強(qiáng)類型的EditorFor<T>方法,同樣該泛型方法已經(jīng)被類型推斷過(guò)了,看泛型方法的定義:
public static class EditorExtensions { public static MvcHtmlString EditorFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression); }
上述代碼中加粗的部分正是關(guān)鍵所在,這里擴(kuò)展的其實(shí)是我們?cè)赩iew中引入的強(qiáng)類型參數(shù)的HtmlHelper<MvcApplication4.Models.Customer>,這樣任何圍繞HtmlHelper<T>進(jìn)行擴(kuò)展的擴(kuò)展方法都會(huì)最終使用到類型ViewModel;
對(duì)于ViewModel的呈現(xiàn)一直都是被系統(tǒng)控制著,雖然一個(gè)簡(jiǎn)單的字符串類型字段可以用一個(gè)文本框的HtmlDom結(jié)構(gòu)方式呈現(xiàn)出來(lái),但是那僅僅是代表著沒(méi)有任何業(yè)務(wù)概念的功能性設(shè)置,也就是出發(fā)點(diǎn)是從CLR類型系統(tǒng)考慮的,而不是特定領(lǐng)域角度;如果這個(gè)字符串代表著某種業(yè)務(wù)概念,那么我們希望通過(guò)更人性化的方式讓用戶使用,而不是一個(gè)硬生生的文本框;我們可能會(huì)需要提供了一個(gè)供自動(dòng)輸入提示的HtmlDom結(jié)構(gòu),該結(jié)構(gòu)可能還需要其他的UI成員協(xié)助,如:自動(dòng)提示可能需要JS、后臺(tái)Service接口等一系列成員相互協(xié)調(diào)完成;
這是一個(gè)簡(jiǎn)單的需求,在大型項(xiàng)目中這樣的功能很常見(jiàn),也是到處會(huì)使用到,不單單是一個(gè)兩個(gè)頁(yè)面,N多頁(yè)面都會(huì)有一點(diǎn)點(diǎn)的差異性,但是整體功能都會(huì)差不多,這樣我們只需要在設(shè)計(jì)的時(shí)候適當(dāng)?shù)奶峁┮恍┙涌诰涂梢粤耍?/p>
那么ASP.NETMVC是如何生成前臺(tái)所需要的HtmlDom結(jié)構(gòu)的呢?前面一章我們總結(jié)了,對(duì)于ViewModel的呈現(xiàn)形式只會(huì)有兩種,一種是Edit一種是Display,不會(huì)有其他的呈現(xiàn)形式,所以在圍繞著HtmlHelper對(duì)象的擴(kuò)展方法中大多數(shù)都是以這種類別區(qū)分的,Edit一組,Display一組;
到目前位置我們已經(jīng)知道ViewModel與View之間的橋梁是Model元數(shù)據(jù),可以簡(jiǎn)單的理解為HtmlHelper<T> 一系列擴(kuò)展方法都是通過(guò)獲取Model元數(shù)據(jù)信息來(lái)控制到底需要輸出什么形式的HtmlDom結(jié)構(gòu),而Model元數(shù)據(jù)都是通過(guò)Model元數(shù)據(jù)控制特性來(lái)完成的,這就可以通過(guò)控制Model元數(shù)據(jù)來(lái)控制Model的呈現(xiàn)細(xì)節(jié);
public class Address { [UIHint("CustomAddress")] [Display(Name = "地址")] public string AddressId { get; set; } }
我們?cè)贏ddress類型中為AddressId屬性加上一個(gè)UIHint類型的特性,其實(shí)意思是想說(shuō)明我們?cè)诔绦騼?nèi)部使用的是使用地址ID,而在現(xiàn)實(shí)的時(shí)候我們希望將原來(lái)很單調(diào)的地址ID編程一個(gè)更人性化的地址顯示方式,比如:位于什么省、什么市等等一些其他的地理信息;
在ASP.NETMVC內(nèi)部有一個(gè)internal static class TemplateHelpers 類型的模板輔助類,該類是大部分模板化輸出的幫助接口,在該類的內(nèi)部定義了一套模板化使用的字典:
視圖的類型:
static readonly Dictionary<DataBoundControlMode, string> modeViewPaths = new Dictionary<DataBoundControlMode, string> { { DataBoundControlMode.ReadOnly, "DisplayTemplates" }, { DataBoundControlMode.Edit, "EditorTemplates" } };
這里定義了兩組類型,也就是顯示、編輯,這兩組類型將作為查找自定義模板的物理文件夾路徑,同樣ModelMedata中的同一個(gè)屬性在不同的顯示類型中將有不同的判斷作用;
編輯、顯示:
static readonly Dictionary<string, Func<HtmlHelper, string>> defaultDisplayActions = new Dictionary<string, Func<HtmlHelper, string>>(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<string, Func<HtmlHelper, string>> defaultEditorActions = new Dictionary<string, Func<HtmlHelper, string>>(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 }, };
這是兩組顯示模式的模板化操作方法的字典,可以看出同一個(gè)HiddenInput特性將在不同的顯示模式先輸出不同的HtmlDom結(jié)構(gòu);
在我們的ASP.NETMVC項(xiàng)目中要同樣的有兩組文件夾DisplayTemplates、EditorTemplates,這兩個(gè)文件夾將會(huì)是系統(tǒng)查找的路徑;
我們?cè)贒isplayTemplates目錄下創(chuàng)建了一個(gè)用來(lái)顯示客戶地址信息的自定義模板,其實(shí)也就是PartialView部分視圖,用來(lái)重用UI;在該部分視圖中,我們寫(xiě)點(diǎn)測(cè)試數(shù)據(jù):
@model string <div> <h3>@Model</h3> <h3>地址:上海市、長(zhǎng)寧區(qū)</h3> <h3>氣溫:-1~10</h3> <h3>交通:方便出行</h3> </div>
然后我們刷新一下界面,看如何個(gè)性化了地址顯示;
這樣我們就可以控制細(xì)粒度的ViewModel顯示;
其實(shí)我們應(yīng)該能夠領(lǐng)悟到通過(guò)PartialView與HtmlHelper彼此互相嵌套能讓原本單一的部分視圖變成一個(gè)強(qiáng)大的具有設(shè)計(jì)模式功能的模板裝飾者模式;想想看,如果我們將這里的AddressId類型再設(shè)計(jì)成復(fù)雜的類型,然后在該復(fù)雜的類型內(nèi)部我們嵌套了一個(gè)原本在其他地方使用的地址類型ViewModel,而且剛好該類型也具有相應(yīng)的部分是視圖,這樣我們就可以將ViewModel的嵌套使用與PartialView嵌套使用相結(jié)合,這樣就可以使用類似設(shè)計(jì)模式中的裝飾者模式來(lái)完成很多UI上的展現(xiàn)重用功能;
作者:王清培
出處:http://wangqingpei557.blog.51cto.com/
本文版權(quán)歸作者和51CTO共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
本文名稱:.NET/ASP.NETMVC深入剖析Model元數(shù)據(jù)、HtmlHelper、自定義模板、模板的裝飾者模式(三)
文章地址:http://www.rwnh.cn/article20/gjhico.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、外貿(mào)網(wǎng)站建設(shè)、云服務(wù)器、品牌網(wǎng)站制作、App設(shè)計(jì)、網(wǎng)站收錄
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)