您的位置:首页 > 编程语言 > ASP

[ASP.NET MVC]为HtmlHelper添加一个RadioButtonList扩展方法

2012-03-15 17:38 846 查看
前面一篇文章中,我们通过对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进行单独维护。

[code]
[code] public class Person

{

 public string Name{ get; set;}

 public string Gender{ get; set;}

[Display(Name = "Marital Status")]

 public string MaritalStatus{ get; set;}

 public string Country{ get; set;}

}

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

[code]
[code] @using System.Web.UI.WebControls

@model Person

@{

ViewBag.Title = "Index";

}

@using (Html.BeginForm())

{ 

<table id="container">

<tr>

<td class="label">@Html.LabelFor(m => m.Name):</td>

<td>@Html.EditorFor(m => m.Name)</td>

</tr>

 <tr>

<td class="label">@Html.LabelFor(m => m.Gender):</td>

<td>@Html.RadioButtonListFor(m => m.Gender, "Gender")</td>

</tr>

 <tr>

<td class="label">@Html.LabelFor(m => m.MaritalStatus):</td>

<td>@Html.RadioButtonListFor(m => m.MaritalStatus, "MaritalStatus")</td>

</tr>

 <tr>

<td class="label">@Html.LabelFor(m => m.Country):</td>

<td>@Html.RadioButtonListFor(m => m.Country, "Country", RepeatDirection.Vertical)</td>

</tr> 

<tr>

<td colspan="2"><input type="submit" value="Save" /></td>

</tr>

</table>

}

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





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

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

[code]
[code] public class CodeDescription

{

 public string Code{ get; set;}

 public string Description{ get; set;}

public string Category{get;set;}


 public CodeDescription(string code, string description, string category)

{

 this.Code = code;

 this.Description = description;

 this.Category = category;

}

}

public static class CodeManager

{

 private static CodeDescription[] codes = new CodeDescription[]

{

 new CodeDescription("M","Male","Gender"),

 new CodeDescription("F","Female","Gender"),

 new CodeDescription("S","Single","MaritalStatus"),

 new CodeDescription("M","Married","MaritalStatus"),

 new CodeDescription("CN","China","Country"),

 new CodeDescription("US","Unite States","Country"),

 new CodeDescription("UK","Britain","Country"),

 new CodeDescription("SG","Singapore","Country")

};

 public static Collection<CodeDescription> GetCodes(string category)

{

 Collection<CodeDescription> codeCollection = new Collection<CodeDescription>();

 foreach(var code in codes.Where(code=>code.Category == category))

{

 codeCollection.Add(code);

}

 return codeCollection;

}

}

[/code]
[/code]

三、RadioButtonList/RadioButtonListFor扩展方法

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


[code]
[code] public staticclass RadioButtonListExtensions

{

 public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name,string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal, IDictionary<string, object> htmlAttributes = null)

{

 var codes = CodeManager.GetCodes(codeCategory);

 return GenerateHtml(name, codes, repeatDirection, htmlAttributes, null);

}

 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)

{

 var codes = CodeManager.GetCodes(codeCategory);

 

 ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);

 string name = ExpressionHelper.GetExpressionText(expression);

 var attributes = htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata);

 foreach (var item in attributes)

{

 htmlAttributes.Add(item);

}

 string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);

 string stateValue = (string)GetModelStateValue(htmlHelper,fullHtmlFieldName, typeof(string));

 return GenerateHtml(fullHtmlFieldName, codes, repeatDirection, htmlAttributes, stateValue);

}


 internal static object GetModelStateValue<TModel>(HtmlHelper<TModel> htmlHelper, string key, Type destinationType)

{

 ModelState state;

 if (htmlHelper.ViewData.ModelState.TryGetValue(key, out state) && (state.Value != null))

{

 return state.Value.ConvertTo(destinationType, null);

}

 return null;

}


 private static MvcHtmlString GenerateHtml(string name, Collection<CodeDescription> codes, RepeatDirection repeatDirection, IDictionary<string, object> htmlAttributes, string stateValue = null)

{

 TagBuilder table = new TagBuilder("table");

 int i = 0;

 if (repeatDirection == RepeatDirection.Horizontal)

{

 TagBuilder tr = new TagBuilder("tr");

 foreach (var code in codes)

{

 i++;

 string id = string.Format("{0}_{1}", name, i);

 TagBuilder td = new TagBuilder("td");

 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);

 tr.InnerHtml+=td.ToString();

}

 table.InnerHtml = tr.ToString();

}

 else

{

 foreach (var code in codes)

{

 TagBuilder tr = new TagBuilder("tr");

 i++;

 string id = string.Format("{0}_{1}", name, i);

 TagBuilder td = new TagBuilder("td");

 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);

 tr.InnerHtml = td.ToString();

 table.InnerHtml += tr.ToString();

}

}

 return new MvcHtmlString(table.ToString());

}


 private static string GenerateRadioHtml(string name, string id, string labelText, string value, bool isChecked, IDictionary<string, object> htmlAttributes)

{

 StringBuilder sb = new StringBuilder();


 TagBuilder label = new TagBuilder("label");

 label.MergeAttribute("for", id);

 label.SetInnerText(labelText);


 TagBuilder input = new TagBuilder("input");

 input.GenerateId(id);

 input.MergeAttribute("name", name);

 input.MergeAttribute("type", "radio");

 input.MergeAttribute("value", value);

 input.MergeAttributes(htmlAttributes);

 if (isChecked)

{

 input.MergeAttribute("checked", "checked");

}

 sb.AppendLine(input.ToString());

 sb.AppendLine(label.ToString());

 return sb.ToString();

}

}

[/code]
[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: