在《为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
3: string Name { get; set; }
5: [display(Name = "Marital Status")]
7: string[] Country { get; set; }
string Code { get; set; }5: string Category{get;set;}
public CodeDescription(string code,string description,1)">string category)9: this.Code = code;
11: this.Category = category;
13: }15: {17: {19: "F",1)">"Female",
26: };29: Collection<CodeDescription> codeCollection = new Collection<CodeDescription>();
31: {33: }35: }class HomeController : Controller4: {6: }8: public ActionResult Index(Person person)
return this.View(person);
12: }
下面是Index操作对应的View的定义,这是一个Model类型为Person的强类型View。对于Person的三个基于列表的属性,我们分别调用了自定义的扩展方法RadioButtonListFor和CheckBoxListFor进行了绑定。方法的最后两个参数分别代表通过CodeManager维护的列表的组别(Gender、MaritalStatus和Country),和同组RadioButton和CheckBox布局方向(水平或者纵向)。
2: @model Person
4: ViewBag.Title = "Index";
6: @using (Html.BeginForm())
<table id="container">
10: td class="label">@Html.LabelFor(m => m.Name):</td 11: >@Html.EditorFor(m => m.Name) 12: 13: 14: > m.Gender): 15: >@Html.RadioButtonListFor(m => m.Gender,"Gender") 16: 17: 18: > m.MaritalStatus): 19: > m.MaritalStatus,"MaritalStatus") 21: 22: > m.Country): 23: >@Html.CheckBoxListFor(m => m.Country,"Country",RepeatDirection.Vertical)>
28: table>
class ListControlExtensions
5: var codes = CodeManager.GetCodes(codeCategory);
7: }
10: var codes = CodeManager.GetCodes(codeCategory);
string name = ExpressionHelper.GetExpressionText(expression);
14: return ListControlUtil.GenerateHtml(fullHtmlFieldName,Metadata.Model);
16:
19: var codes = CodeManager.GetCodes(codeCategory);
22: static MvcHtmlString CheckBoxListFor<TModel,1)" id="lnum23"> 23: {
25: ModelMetadata Metadata = ModelMetadata.FromLambdaExpression<TModel,1)" id="lnum26"> 26: string name = ExpressionHelper.GetExpressionText(expression);
30: }
ListControlUtil中生成相关Html的逻辑定义如下:
static MvcHtmlString GenerateHtml(string type,1)">object stateValue)
int i = 0;
8: if (repeatDirection == RepeatDirection.Horizontal)
10: TagBuilder tr = "tr");
12: {
14: string id = string.Format("{0}_{1}",name,i);
17: bool isChecked = false;
19: {
21: isChecked = (null != currentValues && currentValues.Contains(code.Code));
23: else
25: string currentValue = stateValue as string;
27: }
29: td.InnerHtml = GenerateradioHtml(name,id,code.Description,code.Code,isChecked,type);
31: }
else
36: in codes)
38: TagBuilder tr = 39: i++;
43: 44: 45: {
49: 50: {
54:
57: table.InnerHtml += tr.ToString();
59: }
61: }
63: string GenerateradioHtml(string id,1)">string labelText,1)">string value,1)">bool isChecked,1)">string type)
65: StringBuilder sb = new StringBuilder();
67: TagBuilder label = "label");
69: label.SetInnerText(labelText);
71: TagBuilder input = "input");
73: input.MergeAttribute("name",name);
75: input.MergeAttribute("value",1)">value);
77: {
79: }
81: sb.AppendLine(label.ToString());
83: }