<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      ASP.NET MVC的Model元數據與Model模板:模板的獲取與執行策略

      當我們調用HtmlHelper或者HtmlHelper<TModel>的模板方法對整個Model或者Model的某個數據成員以某種模式(顯示模式或者編輯模式)進行呈現的時候,通過預先創建的代表Model元數據的ModelMetadata對象都可以找到相應的模板。如果模板對應著某個自定義的分部View,那么只需要執行該View即可;對于默認模板,則直接可以得到相應的HTML。本篇文章著重討論模板的獲取和執行機制,不過在這之前,順便來討論一下DataTypeAttribute和模板的關系。[本文已經同步到《How ASP.NET MVC Works?》中]

      一、 DataTypeAttribute和模板有何關系?

      通過《初識Model元數據》針對Model元數據定義的介紹,我們知道通過DataTypeAttribute特性對目標元素設置的數據類型最終會反映在表示Model元數據的ModelMetadata對象的DataTypeName屬性上。此外,對于某些設置的數據類型,比如Date、Time、Duration和Currency等,還會隨之創建一個DisplayFormatAttribute應用到ModelMetadata上。那么ModelMetadata的DataTypeName屬性對目標元素的最終呈現具有怎樣的影響呢?

      實際上在模板匹配的過程中會將ModelMetadata的DataTypeName屬性當作模板名稱來看待,所以下面兩種形式的Model類型定義可以看成是等效的。通過UIHintAttribute特性設置的模板名稱和通過DataTypeAttribute特性設置的數據類型的唯一不同之處在于前者具有更高的優先級。換句話說,如果將UIHintAttribute和DataTypeAttribute同時應用到同一個數據成員分別將模板名稱和數據類型設置為ABC和123,自定義模板123只有在模板ABC不存在的情況下才會被使用。

         1: public class Model
         2: {
         3:     [DataType(DataType.Html)]
         4:     public string Foo { get; set; }
         5:  
         6:     [DataType(DataType.MultilineText)]
         7:     public string Bar { get; set; }
         8:  
         9:     [DataType(DataType.Url)]
        10:     public string Baz { get; set; }
        11: }
        12:  
        13: public class Model
        14: {
        15:     [UIHint("Html")]
        16:     public string Foo { get; set; }
        17:  
        18:     [UIHint("MultilineText")]
        19:     public string Bar { get; set; }
        20:  
        21:     [UIHint("Url")]
        22:     public string Baz { get; set; }
        23: }

      實例演示:證明DataTypeName與模板名稱的等效性

      為了證明通過DataTypeAttribute特性設置數據類型在針對目標元素進行可視化呈現過程中被視為模板名稱,我們來做一個簡單的實例演示。在這個實例中我們定義了如下一個表示三角形的數據類型Triangle,其屬性A、B和C是一個Point對象,表示三個角所在的坐標。

         1: public class Triangle
         2: {
         3:     [DataType("PointInfo")]
         4:      public Point A { get; set; }
         5:  
         6:     [DataType("PointInfo")]
         7:      public Point B { get; set; }
         8:  
         9:     [DataType("PointInfo")]
        10:     public Point C { get; set; }
        11: }
        12:  
        13: [TypeConverter(typeof(PointTypeConverter))]
        14: public class Point
        15: {
        16:     public double X { get; set; }
        17:     public double Y { get; set; }
        18:     public Point(double x, double y)
        19:     {
        20:         this.X = x;
        21:         this.Y = y;
        22:     }
        23:  
        24:     public static Point Parse(string point)
        25:     {
        26:         string[] split = point.Split(',');
        27:         if (split.Length != 2)
        28:         {
        29:             throw new FormatException("Invalid point expression.");
        30:         }
        31:         double x;
        32:         double y;
        33:         if (!double.TryParse(split[0], out x) ||!double.TryParse(split[1], out y))
        34:         {
        35:             throw new FormatException("Invalid point expression.");
        36:         }
        37:         return new Point(x, y);
        38:     }
        39: }
        40:  
        41: public class PointTypeConverter : TypeConverter
        42: {
        43:      public override bool CanConvertFrom(ITypeDescriptorContext context,Type sourceType)
        44:     {
        45:         return sourceType == typeof(string);
        46:     }
        47:  
        48:      public override object ConvertFrom(ITypeDescriptorContext context,CultureInfo culture, object value)
        49:     {
        50:         if (value is string)
        51:         {
        52:             return Point.Parse(value as string);
        53:         }
        54:         return base.ConvertFrom(context, culture, value);
        55:     }
        56: }

      對于類型Triangle和Point的定義,有兩點值得注意:其一,Triangle的三個A、B和C屬性上應用了DataTypeAttribute特性并將自定義數據類型設置為PointInfo(不是Point);其二,Point類型上應用了TypeConverterAttribute特性并將TypeConverter類型設置為PointTypeConverter,后者支持源自字符串的類型轉換。通過前面對復雜類型(Complex Type)的介紹,這樣會將Triangle的三個屬性從復雜類型成員轉換成簡單類型成員。根據前提介紹的關于Object模板對數據成員的便利規則,Triangle的這三個屬性才能被最終呈現出來

      現在我們創建一個Model類型為Point的強類型分部View作為模板,并將其命名為PointInfo(和前面通過DataTypeAttribute特性指定的自定義數據類型一致)。我們只為Point定義關于顯示模式的模板,所以我們將該分部View文件放在Views\Shared\DisplayTemplates中。如下面的代碼片斷所示,我們將一個Point對象顯示為(X,Y)的形式。

         1: @model MvcApp.Models.Point
         2: (@Model.X, @Model.Y)

      現在我們創建一個默認的HomeCtroller。如下面的代碼片斷所示,在默認的Index操作方法中我們創建了一個Triangle對象將其呈現在默認的View中。

         1: public class HomeController : Controller
         2: {
         3:     public ActionResult Index()
         4:     {
         5:         Triangle triangle = new Triangle
         6:         {
         7:             A = new Point(1,2),
         8:             B = new Point(2,3),
         9:             C = new Point(3,4)
        10:         };
        11:         return View(triangle);
        12:     }
        13: }

      下面是對應的View的定義,這是一個Model類型為Triangle的強類型View,我們僅僅調用了HtmlHelper<TModel>的DisplayModel方法將作為Model的Triangle對象以顯示模式呈現出來。

         1: @model MvcApp.Models.Triangle
         2: @Html.DisplayForModel()

      運行該Web應用會在瀏覽器中得到如下圖所示的呈現效果,我們可以看到作為我們創建的Triangle對象的A、B和C屬性表示的三個角的坐標是完全按照我們定義的PointInfo模板的方式進行呈現的。

      image

      二、模板的獲取與執行

      當我們調用HtmlHelper或者HtmlHelper<TModel>的模板方法對整個Model或者Model的某個數據成員以某種模式(顯示模式或者編輯模式)進行呈現的時候,通過預先創建的代表Model元數據的ModelMetadata對象都可以找到相應的模板。如果模板對應著某個自定義的分部View,那么只需要執行該View即可;對于默認模板,則直接可以得到相應的HTML。

      根據Model元數據對目標模板的解析是整個模板方法執行流程中最核心的部分,也是本篇討論的重點。我們以針對HtmlHelper<TModel>的擴展方法DisplayFor為例,看看針對通過表達式expression獲取的Model對象是如何以顯示模式呈現出來的。

         1: public static class DisplayExtensions
         2: {
         3:     public static MvcHtmlString DisplayFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string templateName);
         4: }

      在DisplayFor被調用的時候,如果通過參數expression表示的Model獲取表達式是針對某個屬性的,那么屬性名會被獲取出來。然后執行表達式得到一個作為Model的對象,該對象連同屬性名(如果有)一起被用于表示Model元數據的Metadatadata對象。接下來會根據該Metadatadata對象得到一系列表示分部模板View名稱的列表,這些View名稱按照優先級排列如下:

      • 作為參數templateName傳入的模板名稱(如果不為空)。
      • Metadatadata的TemplateHint屬性值(如果不為空)。
      • Metadatadata的DataTypeName屬性值(如果不為空)。
      • 如果Model對象的真實類型為非空值類型,該類型名作為模板View名;否則底層(Underlying)類型名作為模板View名(比如說,對于int?類型則將Int32作為模板View名)。
      • 如果Model對象的真實類型為非復雜類型,則使用String模板(由于非復雜類型能夠實現與String類型之間的轉換,所以可以轉換成String進行呈現)。
      • 在Model的聲明類型為接口情況下,如果該接口繼承自IEnuerable則采用Collection模板。
      • 在Model的聲明類型為接口情況下,使用Object模板。
      • 如果Model聲明類型不是接口類型,按照其類型繼承關系向上追溯知道Object類型,逐個將類型名稱作為模板View名稱。如果聲明類型實現了IEnuerable接口,則將最后的Object替換成Collection。

      對于得到的這個表示列表,會按照先后順序便利所有的元素。針對具體的表示模板View名稱的某個字符串,會根據呈現的模式在指定的路徑(顯示模式和編輯模式分別為“/DisplayTemplates/{TemplateName}”和“/EditorTemplates/{TemplateName}”)去尋找定義模板的View。如果這樣的View存在,則直接執行該View并返回。如果不能找到自定義模板分部View,則根據該模板名稱在默認的模板列表中查找,如果存在名稱匹配的默認模板,則直接返回默認模板對應的HTML。如果默認的模板列表中的名稱均與指定的名稱不匹配,在進入下一次迭代。

      ASP.NET MVC的Model元數據與Model模板:預定義模板
      ASP.NET MVC的Model元數據與Model模板:模板的獲取與執行策略
      ASP.NET MVC的Model元數據與Model模板:將ListControl引入ASP.NET MVC

      posted @ 2012-05-03 14:49  Artech  閱讀(5859)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 免费国产高清在线精品一区| 成人午夜伦理在线观看| 亚洲中文字幕无码专区| 资溪县| 99久久亚洲综合精品成人网| 日韩精品无码区免费专区| 末发育娇小性色xxxxx视频 | 丁香婷婷无码不卡在线| 日韩精品一区二区三区在| 性人久久久久| 97在线碰| 无翼乌口工全彩无遮挡h全彩| 中文字幕亚洲综合第一页| 亚洲嫩模喷白浆在线观看| 亚洲精品天堂一区二区| 亚洲精品福利一区二区三区蜜桃| 亚洲另类无码一区二区三区| 亚洲AV日韩AV综合在线观看| 中国猛少妇色xxxxx| 色久综合色久综合色久综合| 成人年无码av片在线观看| 国产人妻熟女呻吟在线观看 | 五月丁香综合缴情六月小说| 色爱综合另类图片av| 日韩免费美熟女中文av| 精品国产亚洲一区二区三区在线观看| 精品偷拍被偷拍在线观看| 国产午夜福利高清在线观看 | 邵武市| 亚洲熟女乱色综一区二区| 国产天堂亚洲国产碰碰| 精选国产av精选一区二区三区| 元码人妻精品一区二区三区9| 国产不卡一区二区四区| 亚洲国产精品综合久久20| 久久精品亚洲精品国产区| 欧产日产国产精品精品| 国内外成人综合免费视频| 中文字幕av无码不卡| 福利视频在线一区二区| 草裙社区精品视频播放|