[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被有效地生成出来。
二、维护选项列表的组件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/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于为HtmlHelper添加一个RadioButtonList扩展方法的详细内容...