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

ASP.NET MVC 中使用“RadioButtonList”和“CheckBoxList”

2012-03-16 14:39 295 查看

一、有何特别之处?

和我的很多文章一样,旨在提供一种大体的解决方案,本解决方案旨在解决如下一些问题:

通过独立的组件对绑定到ListControl(ASP.NET Web Form的说法)的列表进行单独管理;

自动地调用上面这个组件获取列表信息进行相关Html的生成;

支持ASP.NET MVC原生的Model Binding。

二、实例演示

下面是代表个人信息同时作为Model的Person类型,Gender、MaritalStatus 和Country分别代表性别、婚姻状况和国籍(这里支持多国籍)。

[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]

上述三个属性分别代表CodeManager这个独立组件维护的三个列表,CodeManager和代表列表选项的CodeDescription定义如下:

[code] public class HomeController : Controller

{

public ActionResult Index()

{

 return View(new Person{ Name = "Foo", Gender = "M", MaritalStatus = "S", Country = new string[]{"CN","US"}});

}

[HttpPost]

public ActionResult Index(Person person)

{

return this.View(person);

}

}

[/code]
[/code]
下面是Index操作对应的View的定义,这是一个Model类型为Person的强类型View。对于Person的三个基于列表的属性,我们分别调用了自定义的扩展方法RadioButtonListFor和CheckBoxListFor进行了绑定。方法的最后两个参数分别代表通过CodeManager维护的列表的组别(Gender、MaritalStatus和Country),和同组RadioButton和CheckBox布局方向(水平或者纵向)。

[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.CheckBoxListFor(m => m.Country, "Country", RepeatDirection.Vertical)</td>

</tr> 

<tr>

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

</tr>

</table>

}

[/code]
[/code]
下面是最终呈现出来的效果:





三、两组扩展方法具体实现

现在我们简单地来看看RadioButtonList/RadioButtonListFor和CheckBoxList/CheckBoxListFor这两组扩展方法的实现。我们通过CodeManager得到列表集合,通过HtmlHelper结合 ModelMetadata得到当前数据,最终借助于ListControlUtil的GenerateHtml生成相关的Html。

[code] public static class ListControlExtensions

{

public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, string name, string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)

{

var codes = CodeManager.GetCodes(codeCategory);

return ListControlUtil.GenerateHtml(name, codes, repeatDirection,"radio",null);

}

public static MvcHtmlString RadioButtonListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)

{

var codes = CodeManager.GetCodes(codeCategory);

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

string name = ExpressionHelper.GetExpressionText(expression);

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

return ListControlUtil.GenerateHtml(fullHtmlFieldName, codes, repeatDirection, "radio", metadata.Model);

}


 public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string name, string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)

{

var codes = CodeManager.GetCodes(codeCategory);

 return ListControlUtil.GenerateHtml(name, codes, repeatDirection, "checkbox", null);

}

 public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string codeCategory, RepeatDirection repeatDirection = RepeatDirection.Horizontal)

{

var codes = CodeManager.GetCodes(codeCategory);

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

 string name = ExpressionHelper.GetExpressionText(expression);

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

 return ListControlUtil.GenerateHtml(fullHtmlFieldName, codes, repeatDirection, "checkbox", metadata.Model);

}

}

[/code]

ListControlUtil中生成相关Html的逻辑定义如下:

[code] public static class ListControlUtil

{

 public static MvcHtmlString GenerateHtml(string name, Collection<CodeDescription> codes, RepeatDirection repeatDirection, string type, object stateValue)

{

 TagBuilder table = new TagBuilder("table");

 int i = 0;

 bool isCheckBox = type == "checkbox";

 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");


 bool isChecked = false;

 if (isCheckBox)

{

 IEnumerable<string> currentValues = stateValue as IEnumerable<string>;

 isChecked = (null != currentValues && currentValues.Contains(code.Code));

}

 else

{

 string currentValue = stateValue as string;

 isChecked = (null != currentValue && code.Code == currentValue);

}


 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, isChecked,type);

 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");


 bool isChecked = false;

 if (isCheckBox)

{

 IEnumerable<string> currentValues = stateValue as IEnumerable<string>;

 isChecked = (null != currentValues && currentValues.Contains(code.Code));

}

 else

{

 string currentValue = stateValue as string;

 isChecked = (null != currentValue && code.Code == currentValue);

}


 td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, isChecked, type);

 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, string type)

{

 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", type);

 input.MergeAttribute("value", value);

 if (isChecked)

{

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

}

 sb.AppendLine(input.ToString());

 sb.AppendLine(label.ToString());

 return sb.ToString();

}

}

[/code]

通过对HtmlHelper扩展简化“列表控件”的绑定
为HtmlHelper添加一个RadioButtonList扩展方法
在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: