好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”

在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”

在《 为HtmlHelper添加一个RadioButtonList扩展方法 》中我通过对HtmlHelper和HtmlHelper<Model>的扩展使我们可以采用”RadioButtonList”的方式对一组类型为“radio”的<input>元素进行操作。昨天对对此进行了一些改进,并将“CheckBoxList”的功能添加进来。[源代码从 这里 下载]

一、有何特别之处?

和我的很多文章一样,旨在提供一种大体的解决方案,本解决方案旨在解决如下一些问题:

通过独立的组件对绑定到ListControl(ASP.NET Web Form的说法)的列表进行单独管理; 自动地调用上面这个组件获取列表信息进行相关Html的生成; 支持ASP.NET MVC原生的Model Binding。 二、实例演示

我们还是以《 为HtmlHelper添加一个RadioButtonList扩展方法 》例子来演示RadioButtonList和CheckBoxList用法。下面是代表个人信息同时作为Model的Person类型,Gender、MaritalStatus 和Country分别代表性别、婚姻状况和国籍(这里支持多国籍)。

    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:  }

上述三个属性分别代表CodeManager这个独立组件维护的三个列表,CodeManager和代表列表选项的CodeDescription定义如下:

    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:  }

在默认的HomeController中,我们定义了如下两个Index方法,它们分别用于测试出栈数据(Model->UI)入栈数据(UI-〉Model)的绑定。

    1:   public   class  HomeController : Controller
    2:  {
    3:       public  ActionResult Index()
    4:      {
    5:           return  View( new  Person { Name =  "Foo" , Gender =  "M" , MaritalStatus =  "S" , Country =  new   string []{ "CN" , "US" } });
    6:      }
    7:      [HttpPost]
    8:       public  ActionResult Index(Person person)
    9:      {
   10:           return   this .View(person);
   11:      }
   12:  }

下面是Index操作对应的View的定义,这是一个Model类型为Person的强类型View。对于Person的三个基于列表的属性,我们分别调用了自定义的扩展方法RadioButtonListFor和CheckBoxListFor进行了绑定。方法的最后两个参数分别代表通过CodeManager维护的列表的组别(Gender、MaritalStatus和Country),和同组RadioButton和CheckBox布局方向(水平或者纵向)。

    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.CheckBoxListFor(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:  }

下面是最终呈现出来的效果:

三、两组扩展方法具体实现

现在我们简单地来看看RadioButtonList/RadioButtonListFor和CheckBoxList/CheckBoxListFor这两组扩展方法的实现。我们通过CodeManager得到列表集合,通过HtmlHelper结合 ModelMetadata得到当前数据,最终借助于ListControlUtil的GenerateHtml生成相关的Html。

    1:   public   static   class  ListControlExtensions
    2:  {
    3:       public   static  MvcHtmlString RadioButtonList( this  HtmlHelper htmlHelper,  string  name,  string  codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
    4:      {
    5:          var codes = CodeManager.GetCodes(codeCategory);
    6:           return  ListControlUtil.GenerateHtml(name, codes, repeatDirection, "radio" , null );
    7:      }
    8:       public   static  MvcHtmlString RadioButtonListFor<TModel, TProperty>( this  HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression,  string  codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
    9:      {
   10:          var codes = CodeManager.GetCodes(codeCategory);
   11:          ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
   12:           string  name = ExpressionHelper.GetExpressionText(expression);           
   13:           string  fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
   14:           return  ListControlUtil.GenerateHtml(fullHtmlFieldName, codes, repeatDirection,  "radio" , metadata.Model);
   15:      }
   16:   
   17:       public   static  MvcHtmlString CheckBoxList( this  HtmlHelper htmlHelper,  string  name,  string  codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
   18:      {
   19:          var codes = CodeManager.GetCodes(codeCategory);
   20:           return  ListControlUtil.GenerateHtml(name, codes, repeatDirection,  "checkbox" ,  null );
   21:      }
   22:       public   static  MvcHtmlString CheckBoxListFor<TModel, TProperty>( this  HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression,  string  codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)
   23:      {
   24:          var codes = CodeManager.GetCodes(codeCategory);
   25:          ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
   26:           string  name = ExpressionHelper.GetExpressionText(expression);
   27:           string  fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
   28:           return  ListControlUtil.GenerateHtml(fullHtmlFieldName, codes, repeatDirection,  "checkbox" , metadata.Model);
   29:      }
   30:  }

ListControlUtil中生成相关Html的逻辑定义如下:

    1:   public   static   class  ListControlUtil
    2:  {
    3:       public   static  MvcHtmlString GenerateHtml( string  name, Collection<CodeDescription> codes, RepeatDirection repeatDirection,  string  type,  object  stateValue)
    4:      {
    5:          TagBuilder table =  new  TagBuilder( "table" );
    6:           int  i = 0;
    7:           bool  isCheckBox = type ==  "checkbox" ;
    8:           if  (repeatDirection == RepeatDirection.Horizontal)
    9:          {
   10:              TagBuilder tr =  new  TagBuilder( "tr" );
   11:               foreach  (var code  in  codes)
   12:              {
   13:                  i++;
   14:                   string  id =  string .Format( "{0}_{1}" , name, i);
   15:                  TagBuilder td =  new  TagBuilder( "td" );
   16:   
   17:                   bool  isChecked =  false ;
   18:                   if  (isCheckBox)
   19:                  {
   20:                      IEnumerable< string > currentValues = stateValue  as  IEnumerable< string >;
   21:                      isChecked = ( null  != currentValues && currentValues.Contains(code.Code));
   22:                  }
   23:                   else 
   24:                  {
   25:                       string  currentValue = stateValue  as   string ;
   26:                      isChecked = ( null  != currentValue && code.Code == currentValue);
   27:                  }
   28:   
   29:                  td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, isChecked,type);
   30:                  tr.InnerHtml += td.ToString();
   31:              }
   32:              table.InnerHtml = tr.ToString();
   33:          }
   34:           else 
   35:          {
   36:               foreach  (var code  in  codes)
   37:              {
   38:                  TagBuilder tr =  new  TagBuilder( "tr" );
   39:                  i++;
   40:                   string  id =  string .Format( "{0}_{1}" , name, i);
   41:                  TagBuilder td =  new  TagBuilder( "td" );
   42:   
   43:                   bool  isChecked =  false ;
   44:                   if  (isCheckBox)
   45:                  {
   46:                      IEnumerable< string > currentValues = stateValue  as  IEnumerable< string >;
   47:                      isChecked = ( null  != currentValues && currentValues.Contains(code.Code));
   48:                  }
   49:                   else 
   50:                  {
   51:                       string  currentValue = stateValue  as   string ;
   52:                      isChecked = ( null  != currentValue && code.Code == currentValue);
   53:                  }
   54:   
   55:                  td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, isChecked, type);
   56:                  tr.InnerHtml = td.ToString();
   57:                  table.InnerHtml += tr.ToString();
   58:              }
   59:          }
   60:           return   new  MvcHtmlString(table.ToString());
   61:      }
   62:   
   63:       private   static   string  GenerateRadioHtml( string  name,  string  id,  string  labelText,  string   value ,  bool  isChecked,  string  type)
   64:      {
   65:          StringBuilder sb =  new  StringBuilder();
   66:   
   67:          TagBuilder label =  new  TagBuilder( "label" );
   68:          label.MergeAttribute( "for" , id);
   69:          label.SetInnerText(labelText);
   70:   
   71:          TagBuilder input =  new  TagBuilder( "input" );
   72:          input.GenerateId(id);
   73:          input.MergeAttribute( "name" , name);
   74:          input.MergeAttribute( "type" , type);
   75:          input.MergeAttribute( "value" ,  value );
   76:           if  (isChecked)
   77:          {
   78:              input.MergeAttribute( "checked" ,  "checked" );
   79:          }
   80:          sb.AppendLine(input.ToString());
   81:          sb.AppendLine(label.ToString());
   82:           return  sb.ToString();
   83:      }
   84:  }

通过对HtmlHelper扩展简化“列表控件”的绑定  
为HtmlHelper添加一个RadioButtonList扩展方法  
在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”

作者: Artech
出处: http://artech.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”的详细内容...

  阅读:45次