<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元數(shù)據(jù)與Model模板:將”ListControl”引入ASP.NET MVC

      我們不僅可以創(chuàng)建相應的模板來根據(jù)Model元數(shù)據(jù)控制種類型的數(shù)據(jù)在UI界面上的呈現(xiàn)方法,還可以通過一些擴展來控制Model元數(shù)據(jù)本身。在某些情況下通過這兩者的結合往往可以解決很多特殊數(shù)據(jù)的呈現(xiàn)問題,我們接下來演示的實例就是典型的例子。[本文已經(jīng)同步到《How ASP.NET MVC Works?》中]

      傳統(tǒng)的ASP.NET具有一組重要的控件類型叫做列表控件(ListControl),它的子類包括DropDownList、ListBox、RadioButtonList和CheckBoxList等。對于ASP.NET MVC來說,我們可以通過HtmlHelper/HtmlHelper<TModel>的擴展方法DropDownList/DropDownListFor和ListBox/ListBox在界面上呈現(xiàn)一個下拉框和列表框,但是我們需要手工指定包含的所有列表選項。在一般的Web應用中,尤其是企業(yè)應用中,我們會選擇將這些列表進行單獨地維護,如果我們在構建“列表控件”的時候能夠免去手工提供列表的工作,這無疑會為開發(fā)帶來極大的遍歷,而這實際上很容易實現(xiàn)。[源代碼從這里下載]

      一、實現(xiàn)的效果

      我們先來看看通過該擴展最終實現(xiàn)的效果。在通過Visual Studio的ASP.NET MVC項目模板創(chuàng)建的空Web應用中,我們定義一個作為Model表示員工的Employee類型。如下面的代碼片斷所示,表示性別、學歷、部門和技能的屬性分別應用了RadioButtonListAttribute、DropdownListAttributeListBoxAttributeCheckBoxListAttribubte四個特性。從名稱可以看出來,這四個特性分別代表了目標元素呈現(xiàn)在UI界面上的形式,即對應著傳統(tǒng)ASP.NET Web應用中的四種類型的列表控件:RadioButtonList、DropdownList、ListBox和CheckBoxList。特性中指定的字符串表示預定義列表的名稱。

         1: public class Employee
         2: {
         3:     [DisplayName("姓名")]
         4:     public string Name { get; set; }
         5:  
         6:     [RadioButtonList("Gender")]
         7:     [DisplayName("性別")]
         8:     public string Gender { get; set; }
         9:  
        10:     [DropdownList("Education")]
        11:     [DisplayName("學歷")]
        12:     public string Education { get; set; }
        13:  
        14:     [ListBox("Department")]
        15:     [DisplayName("所在部門")]
        16:     public IEnumerable<string> Departments { get; set; }
        17:  
        18:     [CheckBoxList("Skill")]
        19:     [DisplayName("擅長技能")]
        20:     public IEnumerable<string> Skills { get; set; }
        21: }

      在創(chuàng)建的默認HomeController中,我們定義了如下一個Index操作方法。在該方法中,我們創(chuàng)建了一個具體的Employee對象并對它的所有屬性進行了相應設置,最終將該對象呈現(xiàn)在默認的View中。

         1: public class HomeController : Controller
         2: {
         3:     public ActionResult Index()
         4:     {
         5:         Employee employee = new Employee
         6:         {
         7:             Name       = "張三",
         8:             Gender     = "M",
         9:             Education  = "M",
        10:             Departments= new string[] { "HR", "AD" },
        11:             Skills     = new string[] { "CSharp", "AdoNet" }
        12:         };
        13:         return View(employee);
        14:     }
        15: }

      如下所示的是上面的Index操作對應的View定義,這是一個以Model類型為Employee的強類型View,我們通過調(diào)用HtmlHelper<TModel>的模板方法EditorFor將作為Model的Employee對象的所有屬性以編輯模式呈現(xiàn)出來。

         1: @model Employee
         2: <table>
         3:     <tr>
         4:         <td>@Html.LabelFor(m => m.Name)</td><td>@Html.EditorFor(m => m.Name)</td>
         5:     </tr>
         6:       <tr>
         7:         <td>@Html.LabelFor(m => m.Gender)</td><td>@Html.EditorFor(m => m.Gender)</td>
         8:     </tr>
         9:       <tr>
        10:         <td>@Html.LabelFor(m => m.Education)</td><td>@Html.EditorFor(m => m.Education)</td>
        11:     </tr>
        12:      <tr>
        13:         <td>@Html.LabelFor(m => m.Departments)</td><td>@Html.EditorFor(m => m.Departments)</td>
        14:     </tr>
        15:      <tr>
        16:         <td>@Html.LabelFor(m => m.Skills)</td><td>@Html.EditorFor(m => m.Skills)</td>
        17:     </tr>    
        18: </table>

      下圖體現(xiàn)了該Web應用運行時的效果。我們可以看到,四個屬性分別以四種不同的“列表控件”呈現(xiàn)出來,并且對應在它們上面的四個字定義的列表特性(RadioButtonListAttribute、DropdownListAttribute、ListBoxAttribute和CheckBoxListAttribubte)。

      image

      二、ListItem與ListProvider

      現(xiàn)在對體現(xiàn)在上面演示實例的基于列表數(shù)據(jù)的UI定制的設計進行簡單地介紹。我們首先來定義如下一個表示列表中某個條目(列表項)的類型ListItem,簡單起見,我們緊緊定義Text和Value兩個屬性,它們分別表示顯示的文字和代表的值。比如對于一組表示國家的列表,列表項的Text屬性表示成國家名稱(比如“中國”),具體的值則可能是國家的代碼(比如“CN”)。

         1: public class ListItem
         2: {
         3:     public string Text { get; set; }
         4:     public string Value { get; set; }
         5: }

      我們將提供列表數(shù)據(jù)的組件稱為ListProvider,它們實現(xiàn)了IListProvider接口。如下面的代碼片斷所示,IListProvider具有唯一的方法GetListItems根據(jù)指定的列表名稱獲取所有的列表項。通過實現(xiàn)IListProvider,我們定義了一個默認的DefaultListProvider。簡單起見,DefaultListProvider直接通過一個靜態(tài)字段模擬列表的存儲,在真正的項目中一般會保存在數(shù)據(jù)庫中。DefaultListProvider維護了四組列表,分別表示性別、學歷、部門和技能,它們正好對應著Employee的四個屬性。

         1: public interface IListProvider
         2: {
         3:     IEnumerable<ListItem> GetListItems(string listName);
         4: }
         5: public class DefaultListProvider : IListProvider
         6: {
         7:     private static Dictionary<string, IEnumerable<ListItem>> listItems = new Dictionary<string, IEnumerable<ListItem>>();
         8:     static DefaultListProvider()
         9:     {
        10:         var items = new ListItem[]{
        11:         new ListItem{ Text = "男", Value="M"},
        12:         new ListItem{ Text = "女", Value="F"}};
        13:         listItems.Add("Gender", items);
        14:  
        15:         items = new ListItem[]{            
        16:         new ListItem{ Text = "高中", Value="H"}  , 
        17:         new ListItem{ Text = "大學本科", Value="B"},
        18:         new ListItem{ Text = "碩士", Value="M"} ,                
        19:         new ListItem{ Text = "博士", Value="D"}};
        20:         listItems.Add("Education", items);
        21:  
        22:         items = new ListItem[]{            
        23:         new ListItem{ Text = "人事部", Value="HR"}  , 
        24:         new ListItem{ Text = "行政部", Value="AD"},
        25:         new ListItem{ Text = "IT部", Value="IT"}};
        26:         listItems.Add("Department", items);
        27:  
        28:         items = new ListItem[]{            
        29:         new ListItem{ Text = "C#", Value="CSharp"}  , 
        30:         new ListItem{ Text = "ASP.NET", Value="AspNet"},
        31:         new ListItem{ Text = "ADO.NET", Value="AdoNet"}};
        32:         listItems.Add("Skill", items);
        33:     }
        34:     public IEnumerable<ListItem> GetListItems(string listName)
        35:     {
        36:         IEnumerable<ListItem> items;
        37:         if (listItems.TryGetValue(listName, out items))
        38:         {
        39:             return items;
        40:         }
        41:         return new ListItem[0];
        42:     }
        43: }

      接下來我們定義如下一個ListProviders類型,它的靜態(tài)只讀屬性Current表示當前的ListProvider,而對當前ListProvider的注冊通過靜態(tài)方法SetListProvider來實現(xiàn)。如果沒有對當前ListProvider進行顯式注冊,則默認采用DefaultListProvider。

         1: public static class ListProviders
         2: {
         3:     public static IListProvider Current { get; private set; }
         4:     static ListProviders()
         5:     {
         6:         Current = new DefaultListProvider();
         7:     }
         8:     public static void SetListProvider(Func<IListProvider> providerAccessor)
         9:     {
        10:         Current = providerAccessor();
        11:     }
        12: }

      三、通過對HtmlHelper/HtmlHelper<TModel>的擴展生成“ListControl”的HTML

      基于四種“列表控件”的HTML生成是通過定義HtmlHelper的擴展方法來實現(xiàn)的,如下面的代碼所示,定義在ListControlExtensions中的四個擴展方法實現(xiàn)了針對這四種列表控件的UI呈現(xiàn)。參數(shù)listName表示使用的預定義列表的名稱,而value和values則表示綁定的值。RadioButtonList/DropdownList只允許單項選擇,而ListBox/CheckBoxList允許多項選擇,所以對應的值類型分別是string和IEnumerable<string>。

         1: public static class ListControlExtensions
         2: {
         3:     //其他成員
         4:    public static MvcHtmlString RadioButtonList( this HtmlHelper htmlHelper,string name, string listName, string value)
         5:     {
         6:         return RadioButtonCheckBoxList(htmlHelper, listName, item => 
         7:            htmlHelper.RadioButton(name, item.Value, value == item.Value));
         8:     }        
         9:  
        10:     public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, string listName, IEnumerable<string> values)
        11:     {
        12:         return RadioButtonCheckBoxList(htmlHelper, listName, item => CheckBoxWithValue(htmlHelper, name,  values.Contains(item.Value), item.Value));
        13:     }
        14:  
        15:     public static MvcHtmlString ListBox(this HtmlHelper htmlHelper, string name, string listName, IEnumerable<string> values)
        16:     {
        17:         var listItems = ListProviders.Current.GetListItems(listName);
        18:         List<SelectListItem> selectListItems = new List<SelectListItem>();
        19:         foreach (var item in listItems)
        20:         {
        21:             selectListItems.Add(new SelectListItem { Value = item.Value, 
        22:                 Text = item.Text, 
        23:                 Selected = values.Any(value => value == item.Value) });
        24:         }
        25:         return htmlHelper.ListBox(name, selectListItems);
        26:     }
        27:  
        28:     public static MvcHtmlString DropDownList(this HtmlHelper htmlHelper, string name, string listName, string value)
        29:     {
        30:         var listItems = ListProviders.Current.GetListItems(listName);
        31:         List<SelectListItem> selectListItems = new List<SelectListItem>();
        32:         foreach (var item in listItems)
        33:         {
        34:             selectListItems.Add(new SelectListItem { Value = item.Value, 
        35:                 Text = item.Text, Selected = value == item.Value});
        36:         }
        37:         return htmlHelper.DropDownList(name, selectListItems);
        38:     }
        39: }

      從上面的代碼片斷可以看到,在ListBox和DropDownList方法中我們通過當前的ListProvider獲取指定列表名稱的所有列表項并生成相應的SelectListItem列表,最終通過調(diào)用HtmlHelper現(xiàn)有的擴展方法ListBox和DropDownList實現(xiàn)HTML的呈現(xiàn)。而RadioButtonList和MvcHtmlString最終調(diào)用了輔助方法RadioButtonCheckBoxList顯示了最終的HTML生成,該方法定義如下。

         1: public static class ListControlExtensions
         2: {
         3:     public static MvcHtmlString CheckBoxWithValue(this HtmlHelper htmlHelper, string name, bool isChecked, string value)
         4:     {
         5:         string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
         6:         ModelState modelState;
         7:  
         8:         //將ModelState設置為表示是否勾選布爾值
         9:         if (htmlHelper.ViewData.ModelState.TryGetValue(fullHtmlFieldName, out modelState))
        10:         {
        11:             htmlHelper.ViewData.ModelState.SetModelValue(fullHtmlFieldName, new ValueProviderResult(isChecked, isChecked.ToString(), CultureInfo.CurrentCulture));
        12:         }
        13:         MvcHtmlString html;
        14:         try
        15:         {
        16:             html = htmlHelper.CheckBox(name, isChecked);
        17:         }
        18:         finally
        19:         {
        20:             //將ModelState還原
        21:             if (null != modelState)
        22:             {
        23:                 htmlHelper.ViewData.ModelState[fullHtmlFieldName] = modelState;
        24:             }
        25:         }
        26:         string htmlString = html.ToHtmlString();
        27:         var index = htmlString.LastIndexOf('<');
        28:         //過濾掉類型為"hidden"的<input>元素
        29:         XElement element = XElement.Parse(htmlString.Substring(0, index));
        30:         element.SetAttributeValue("value", value);
        31:         return new MvcHtmlString(element.ToString());
        32:     }
        33:  
        34:     private static MvcHtmlString RadioButtonCheckBoxList(HtmlHelper htmlHelper, string listName, Func<ListItem, MvcHtmlString> elementHtmlAccessor)
        35:     {
        36:         var listItems = ListProviders.Current.GetListItems(listName);
        37:         TagBuilder table = new TagBuilder("table");
        38:         TagBuilder tr = new TagBuilder("tr");
        39:         foreach (var listItem in listItems)
        40:         {
        41:             TagBuilder td = new TagBuilder("td");
        42:             td.InnerHtml += elementHtmlAccessor(listItem).ToHtmlString();
        43:             td.InnerHtml += listItem.Text;
        44:             tr.InnerHtml += td.ToString();
        45:         }
        46:         table.InnerHtml = tr.ToString();
        47:         return new MvcHtmlString(table.ToString());
        48:     }
        49: }

      方法RadioButtonCheckBoxList在生成RadioButtonList和CheckBoxList的時候才用<table>進行布局。組成RadioButtonList的單個RadioButton最終是調(diào)用HtmlHelper現(xiàn)有的擴展方法RadioButton生成的,而CheckBoxList中的CheckBox則是通過調(diào)用我們自定義的CheckBoxWithValue方法生成的。CheckBoxWithValue最終還是調(diào)用HtmlHelper現(xiàn)有的擴展方法CheckBox生成單個CheckBox對應的HTML,但是方法值支持布爾值的綁定,并且會生成一個在這里不需要的Hidden元素,所以我們不得不在調(diào)用該方法的前后作一些手腳。

      四、ListAttribute

      現(xiàn)在我們來介紹應用在Employee屬性上的四個特性的定義。如下面的代碼片斷所示,基于四種“列表控件”的特性均繼承自抽象特性ListAttribute。ListAttribute實現(xiàn)了IMetadataAware接口,在實現(xiàn)的OnMetadataCreated方法中將在構造函數(shù)中指定的代表列表名稱的ListName屬性添加到表示Model元數(shù)據(jù)的ModelMetadata對象的AdditionalValues屬性中。四個具體的列表特性重寫了OnMetadataCreated方法,并在此基礎上將ModelMetadata的TemplateHint分別設置為DropdownList、ListBox、RadioButtonList和CheckBoxList。

         1: [AttributeUsage(AttributeTargets.Property)]
         2: public abstract class ListAttribute : Attribute, IMetadataAware
         3: {
         4:     public string ListName { get; private set; }        
         5:     public ListAttribute(string listName)
         6:     {
         7:         this.ListName = listName;
         8:     }
         9:     public virtual void OnMetadataCreated(ModelMetadata metadata)
        10:     {
        11:         metadata.AdditionalValues.Add("ListName", this.ListName);
        12:     }
        13: }
        14:  
        15: [AttributeUsage(AttributeTargets.Property)]
        16: public class DropdownListAttribute : ListAttribute
        17: {
        18:     public DropdownListAttribute(string listName)
        19:         : base(listName)
        20:     { }
        21:     public override void OnMetadataCreated(ModelMetadata metadata)
        22:     {
        23:         base.OnMetadataCreated(metadata);
        24:         metadata.TemplateHint = "DropdownList";
        25:     }
        26: }
        27:  
        28: [AttributeUsage(AttributeTargets.Property)]
        29: public class ListBoxAttribute : ListAttribute
        30: {
        31:     public ListBoxAttribute(string listName)
        32:         : base(listName)
        33:     { }
        34:     public override void OnMetadataCreated(ModelMetadata metadata)
        35:     {
        36:         base.OnMetadataCreated(metadata);
        37:         metadata.TemplateHint = "ListBox";
        38:     }
        39: }
        40:  
        41: [AttributeUsage(AttributeTargets.Property)]
        42: public class RadioButtonListAttribute : ListAttribute
        43: {
        44:     public RadioButtonListAttribute(string listName)
        45:         : base(listName)
        46:     { }
        47:  
        48:     public override void OnMetadataCreated(ModelMetadata metadata)
        49:     {
        50:         base.OnMetadataCreated(metadata);
        51:         metadata.TemplateHint = "RadioButtonList";
        52:     }
        53: }
        54:  
        55: [AttributeUsage(AttributeTargets.Property)]
        56: public class CheckBoxListAttribute : ListAttribute
        57: {
        58:     public CheckBoxListAttribute(string listName)
        59:         : base(listName)
        60:     { }
        61:  
        62:     public override void OnMetadataCreated(ModelMetadata metadata)
        63:     {
        64:         base.OnMetadataCreated(metadata);
        65:         metadata.TemplateHint = "CheckBoxList";
        66:     }
        67: }

      五、模板View的定義

      由于四個具體的ListAttribute已經(jīng)對表示模板名稱的ModelMetadata的TemplateHint進行了設置,那么我們針對它們定義相應的分部View作為對應的模板,那么在調(diào)用HtmlHelper/HtmlHelper<TModel>相應模板方法的時候就會按照這些模板對目標元素進行呈現(xiàn)。實現(xiàn)如上圖所示的效果的四個模板定義如下,它們被保存在View\Shared\EditorTemplates目錄下面。

         1: DropdownList.cshtml:
         2: @model string
         3: @{    
         4:     string listName = (string)ViewData.ModelMetadata.AdditionalValues["ListName"];
         5:     @Html.DropDownList("",listName,Model)
         6: }
         7:  
         8: ListBox.cshtml:
         9: @model IEnumerable<string>
        10: @{    
        11:     string listName = (string)ViewData.ModelMetadata.AdditionalValues["ListName"];
        12:     @Html.ListBox("",listName,Model)   
        13: }
        14:  
        15: RadioButtonList.cshtml:
        16: @model string
        17: @{    
        18:     string listName = (string)ViewData.ModelMetadata.AdditionalValues["ListName"];
        19:     @Html.RadioButtonList("",listName,Model)
        20: }
        21:  
        22: CheckBoxList.cshtml:
        23: @model IEnumerable<string>
        24: @{    
        25:     string listName = (string)ViewData.ModelMetadata.AdditionalValues["ListName"];
        26:     @Html.CheckBoxList("", listName, Model)
        27:  }

       

      ASP.NET MVC的Model元數(shù)據(jù)與Model模板:預定義模板
      ASP.NET MVC的Model元數(shù)據(jù)與Model模板:模板的獲取與執(zhí)行策略
      ASP.NET MVC的Model元數(shù)據(jù)與Model模板:將ListControl引入ASP.NET MVC

      posted @ 2012-05-04 07:44  Artech  閱讀(9185)  評論(31)    收藏  舉報
      主站蜘蛛池模板: 成人无码午夜在线观看| 亚洲码和欧洲码一二三四| 欧美成人精品三级网站| 中文字幕人妻无码一区二区三区| 久久一本人碰碰人碰| 视频一区二区三区四区久久| 亚洲人成网线在线播放VA| 国产精品一区二区三区四| 久久人与动人物a级毛片| 老司机午夜精品视频资源| 蜜臀av一区二区三区精品| 亚洲精品中文字幕尤物综合| WWW丫丫国产成人精品| 拍真实国产伦偷精品| 可以在线观看的亚洲视频| 国产成人午夜在线视频极速观看 | bt天堂新版中文在线| 无码任你躁久久久久久久| 18禁动漫一区二区三区| 真人性囗交视频| 河源市| 日本国产精品第一页久久| 亚洲av无码成人精品区一区| av一区二区中文字幕| 国产老熟女视频一区二区| 精品一区二区三区在线观看l| 蜜桃av无码免费看永久| 亚洲第一区二区国产精品| 老鸭窝在线视频| 亚洲熟妇熟女久久精品综合 | 免费观看全黄做爰大片| 久久国产精品精品国产色| 视频二区中文字幕在线| 国产亚洲精品福利在线无卡一| 欧美奶涨边摸边做爰视频| 一区二区三区四区亚洲自拍| 福利一区二区不卡国产| 免费看黄片一区二区三区| 色婷婷亚洲精品综合影院| 麻豆一区二区中文字幕| 日本无产久久99精品久久|