zoukankan      html  css  js  c++  java
  • [ASP.NET MVC]为HtmlHelper添加一个RadioButtonList扩展方法

    前面一篇文章中,我们通过对HtmlHelper的扩展简化了对DropDownList(Single-Line-Select)和ListBox(Multiple-Line-Select)的绑定,以及对作为数据源的列表进行单独维护。现在我们为HtmlHelper/HtmlHelper<Model>添加一个RadioButtonList/RadioButtonListFor扩展方法实现一组RadioButton的绑定。[源代码从这里下载]

    一、RadioButtonListFor的使用

    我们先来显示一下扩展的RadioButtonListFor的方法的用法。如下所示的是作为Model的Person类型,其Gender(Male/Female)、MaritalStatus(Single/Married)和Country的选项列表通过独立的组件CodeManager进行单独维护。

       1: public class Person
       2: {
       3:     public string Name { get; set; }
       4:     public string Gender { get; set; }
       5:     [Display(Name = "Marital Status")]
       6:     public string MaritalStatus { get; set; }
       7:     public string Country { get; set; }
       8: }

    在一个针对Person对象进行编辑的强类型View(以Person作为Model)中我们进行了如下的定义。RadioButtonListFor方的最后一个参数(“Gender”、“MaritalStatus”和“Country”)表示对应列表的类别。

       1: @using System.Web.UI.WebControls
       2: @model Person
       3: @{
       4:     ViewBag.Title = "Index";
       5: }
       6: @using (Html.BeginForm())
       7: { 
       8:     <table id="container">
       9:         <tr>
      10:             <td class="label">@Html.LabelFor(m => m.Name):</td>
      11:             <td>@Html.EditorFor(m => m.Name)</td>
      12:         </tr>
      13:          <tr>
      14:             <td class="label">@Html.LabelFor(m => m.Gender):</td>
      15:             <td>@Html.RadioButtonListFor(m => m.Gender, "Gender")</td>
      16:         </tr>
      17:          <tr>
      18:             <td class="label">@Html.LabelFor(m => m.MaritalStatus):</td>
      19:             <td>@Html.RadioButtonListFor(m => m.MaritalStatus, "MaritalStatus")</td>
      20:         </tr>
      21:          <tr>
      22:             <td class="label">@Html.LabelFor(m => m.Country):</td>
      23:             <td>@Html.RadioButtonListFor(m => m.Country, "Country", RepeatDirection.Vertical)</td>
      24:         </tr> 
      25:         <tr>
      26:             <td colspan="2"><input type="submit" value="Save" /></td>
      27:         </tr>      
      28:     </table>    
      29: }

    下面这张图表示上面这个View在浏览器中呈现出来的样式,我们可以看到三组RadioButton被有效地生成出来。

    image

    二、维护选项列表的组件CodeManager

    由于在一个应用中,作为绑定到“列表控件”上的选项列表可能会有很多,将它们进行单独地维护是一个理想的选择。作为模拟,我们创建了如下一个简单的CodeManager组件。我们将列表中的某个选项通过CodeDescription,其三个属性Code、Description分别表示其“值”和“显示文本”,Category表示类别(通过它对列表项进行分组)。CodeManager通过一个静态字段作为列表数据的存储,上面例子中使用到的三组列表维护于此。GetCodes方法用于返回指定“类别”的列表选项。

       1: public class CodeDescription
       2: {
       3:     public string Code { get; set; }
       4:     public string Description { get; set; }
       5:     public string Category{get;set;}
       6:  
       7:     public CodeDescription(string code, string description, string category)
       8:     {
       9:         this.Code = code;
      10:         this.Description = description;
      11:         this.Category = category;
      12:     }
      13: }
      14: public static class CodeManager
      15: {
      16:     private static CodeDescription[] codes = new CodeDescription[]
      17:     {
      18:         new CodeDescription("M","Male","Gender"),
      19:         new CodeDescription("F","Female","Gender"),
      20:         new CodeDescription("S","Single","MaritalStatus"),
      21:         new CodeDescription("M","Married","MaritalStatus"),
      22:         new CodeDescription("CN","China","Country"),
      23:         new CodeDescription("US","Unite States","Country"),
      24:         new CodeDescription("UK","Britain","Country"),
      25:         new CodeDescription("SG","Singapore","Country")
      26:     };
      27:     public static Collection<CodeDescription> GetCodes(string category)
      28:     {
      29:         Collection<CodeDescription> codeCollection = new Collection<CodeDescription>();
      30:         foreach(var code in codes.Where(code=>code.Category == category))
      31:         {
      32:             codeCollection.Add(code);
      33:         }
      34:         return codeCollection;
      35:     }
      36: }

    三、RadioButtonList/RadioButtonListFor扩展方法

    如下所示的是RadioButtonList/RadioButtonListFor两个扩展方法的定义,参数codeCategory表示作为数据源的列表类别,而RepeatDirection 枚举类型则代表同组的RadioButton的排列方向,默认为水平。从上面的例子我们可以看到,我们通过这个参数将名称为Country的RadioButtonList进行了纵向排列。通过Html生成代码我们可以看出,我们采用了Table作为布局方式,实际上ASP.NET的RadioButtonList也是这么做的。

       1: public static  class RadioButtonListExtensions
       2: {
       3:     public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name,  string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal, IDictionary<string, object> htmlAttributes = null)
       4:     {
       5:         var codes = CodeManager.GetCodes(codeCategory);
       6:         return GenerateHtml(name, codes, repeatDirection, htmlAttributes, null);
       7:     }
       8:     public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string codeCategory, RepeatDirection repeatDirection =  RepeatDirection.Horizontal, IDictionary<string, object> htmlAttributes = null)
       9:     {
      10:         var codes = CodeManager.GetCodes(codeCategory);
      11:         
      12:         ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
      13:         string name = ExpressionHelper.GetExpressionText(expression);
      14:         var attributes = htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata);
      15:         foreach (var item in attributes)
      16:         {
      17:             htmlAttributes.Add(item);
      18:         }
      19:         string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
      20:         string stateValue = (string)GetModelStateValue(htmlHelper,fullHtmlFieldName, typeof(string));
      21:         return GenerateHtml(fullHtmlFieldName, codes, repeatDirection, htmlAttributes, stateValue);
      22:     }
      23:  
      24:     internal static object GetModelStateValue<TModel>(HtmlHelper<TModel> htmlHelper, string key, Type destinationType)
      25:     {
      26:         ModelState state;
      27:         if (htmlHelper.ViewData.ModelState.TryGetValue(key, out state) && (state.Value != null))
      28:         {
      29:             return state.Value.ConvertTo(destinationType, null);
      30:         }
      31:         return null;
      32:     }
      33:  
      34:     private static MvcHtmlString GenerateHtml(string name, Collection<CodeDescription> codes, RepeatDirection repeatDirection, IDictionary<string, object> htmlAttributes, string stateValue = null)
      35:     {
      36:         TagBuilder table = new TagBuilder("table");
      37:         int i = 0;
      38:         if (repeatDirection == RepeatDirection.Horizontal)
      39:         {
      40:             TagBuilder tr = new TagBuilder("tr");
      41:             foreach (var code in codes)
      42:             {
      43:                 i++;
      44:                 string id = string.Format("{0}_{1}", name, i);
      45:                 TagBuilder td = new TagBuilder("td");
      46:                 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);
      47:                 tr.InnerHtml+=td.ToString();
      48:             }
      49:             table.InnerHtml = tr.ToString();
      50:         }
      51:         else
      52:         {
      53:             foreach (var code in codes)
      54:             {
      55:                 TagBuilder tr = new TagBuilder("tr");
      56:                 i++;
      57:                 string id = string.Format("{0}_{1}", name, i);
      58:                 TagBuilder td = new TagBuilder("td");
      59:                 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);
      60:                 tr.InnerHtml = td.ToString();
      61:                 table.InnerHtml += tr.ToString();
      62:             }
      63:         }
      64:         return new MvcHtmlString(table.ToString());
      65:     }
      66:  
      67:     private static string GenerateRadioHtml(string name, string id, string labelText, string value, bool isChecked, IDictionary<string, object> htmlAttributes)
      68:     {
      69:         StringBuilder sb = new StringBuilder();
      70:  
      71:         TagBuilder label = new TagBuilder("label");
      72:         label.MergeAttribute("for", id);
      73:         label.SetInnerText(labelText);
      74:  
      75:         TagBuilder input = new TagBuilder("input");
      76:         input.GenerateId(id);
      77:         input.MergeAttribute("name", name);
      78:         input.MergeAttribute("type", "radio");
      79:         input.MergeAttribute("value", value);
      80:         input.MergeAttributes(htmlAttributes);
      81:         if (isChecked)
      82:         {
      83:             input.MergeAttribute("checked", "checked");
      84:         }
      85:         sb.AppendLine(input.ToString());
      86:         sb.AppendLine(label.ToString());
      87:         return sb.ToString();
      88:     }
      89: }
    作者:Artech
    出处:http://artech.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    汇编随笔(第一章 基础知识)
    排序集锦(rough)
    如何让编写的Java代码规范整洁
    二分法查询数据java实现
    归并排序的学习与java实现
    小白的软件测试之路
    PyInstaller打包python脚本
    数据库SQL优化总结
    JQuery选择器
    软件测试面试题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2398421.html
Copyright © 2011-2022 走看看