在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”的详细内容...