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”
相关文章推荐
- 在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”
- 在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”
- ASP.NET MVC 3 CheckBoxList 的使用
- ASP.NET MVC 3 CheckBoxList 的使用
- ASP.NET中 RadioButtonList(单选按钮组),CheckBoxList(复选框组),DropDownList(下拉框),ListBox(列表框),BulletedList(无序列表)的使用前台绑定
- ASP.NET的checkboxlist,RadioButtonList,FileUpload,image控件的综合使用
- ASP.NET MVC 3 CheckBoxList 的使用
- ASP.NET MVC 3 CheckBoxList 的使用
- ASP.NET MVC 3 CheckBoxList 的使用
- ASP.NET MVC 3.0 知识记要(2)【RadioButtonList、CheckBoxList】
- asp.net中repeater嵌套CheckBoxList,RadioButtonList来完成投票
- ASP.NET服务器端控件RadioButtonList,DropDownList,CheckBoxList的取值、赋值用法
- asp.net中repeater嵌套CheckBoxList,RadioButtonList来完成投票
- ASP.NET中CheckBoxList复选框列表控件详细使用方法
- Asp.Net mvc CheckBox,RadioButton使用方法
- ASP.NET服务器端控件RadioButtonList,DropDownList,CheckBoxList的取值、赋值用法
- ASP.NET服务器端控件RadioButtonList,DropDownList,CheckBoxList的取值、赋值用法
- 在Asp.Net MVC中使用ModelBinding构造Array、List、Collection以及Dictionary
- asp.net mvc中构建htmlHelper的checkboxlist
- Asp.net MVC 使用PagedList(新的已更名 为X.PagedList.Mvc) 分页