[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的绑定。[源代码从这里下载]
[/code]
[/code]
在一个针对Person对象进行编辑的强类型View(以Person作为Model)中我们进行了如下的定义。RadioButtonListFor方的最后一个参数(“Gender”、“MaritalStatus”和“Country”)表示对应列表的类别。
[/code]
[/code]
下面这张图表示上面这个View在浏览器中呈现出来的样式,我们可以看到三组RadioButton被有效地生成出来。
[/code]
[/code]
[/code]
[/code]
一、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]
相关文章推荐
- [ASP.NET MVC]为HtmlHelper添加一个RadioButtonList扩展方法
- ASP.NET MVC 3 扩展之给 HtmlHelper 扩展一个 RadioButtonList
- ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法
- ASP.NET MVC HtmlHelper 类的扩展方法
- ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法
- ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法
- dhl: 在 ASP.NET MVC 中创建自定义 HtmlHelper 使用扩展方法创建 HTML Helper
- Asp.Net MVC对类HtmlHelper的自定义扩展方法以及如何调用
- ASP.NET MVC扩展之HtmlHelper辅助方法
- asp.net MVC添加HtmlHelper扩展示例和用法
- asp.net mvc htmlhelper 扩展方法
- ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法
- 转:ASP.NET MVC扩展之HtmlHelper辅助方法
- ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法
- 在ASP.NET MVC下扩展一个带验证的RadioButtonList
- ASP.NET MVC---自定义HtmlHelper方法
- ASP.NET MVC 中出现的 方法 中的 this 关键字 用法 (this HtmlHelper helper)
- ASP.NET MVC HtmlHelper扩展之Calendar日期时间选择
- asp.net mvc 分页控件:HtmlHelper扩展
- Asp.Net MVC 扩展 Html.ImageFor 方法详解