[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)metadata.Model;
21: return GenerateHtml(fullHtmlFieldName, codes, repeatDirection, htmlAttributes, stateValue);
22: }
23: private static MvcHtmlString GenerateHtml(string name, Collection<CodeDescription> codes, RepeatDirection repeatDirection, IDictionary<string, object> htmlAttributes, string stateValue = null)
24: {
25: TagBuilder table = new TagBuilder("table");
26: int i = 0;
27: if (repeatDirection == RepeatDirection.Horizontal)
28: {
29: TagBuilder tr = new TagBuilder("tr");
30: foreach (var code in codes)
31: {
32: i++;
33: string id = string.Format("{0}_{1}", name, i);
34: TagBuilder td = new TagBuilder("td");
35: td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);
36: tr.InnerHtml+=td.ToString();
37: }
38: table.InnerHtml = tr.ToString();
39: }
40: else
41: {
42: foreach (var code in codes)
43: {
44: TagBuilder tr = new TagBuilder("tr");
45: i++;
46: string id = string.Format("{0}_{1}", name, i);
47: TagBuilder td = new TagBuilder("td");
48: td.InnerHtml = GenerateRadioHtml(name, id, code.Description, code.Code, (stateValue != null && stateValue == code.Code), htmlAttributes);
49: tr.InnerHtml = td.ToString();
50: table.InnerHtml += tr.ToString();
51: }
52: }
53: return new MvcHtmlString(table.ToString());
54: }
55:
56: private static string GenerateRadioHtml(string name, string id, string labelText, string value, bool isChecked, IDictionary<string, object> htmlAttributes)
57: {
58: StringBuilder sb = new StringBuilder();
59:
60: TagBuilder label = new TagBuilder("label");
61: label.MergeAttribute("for", id);
62: label.SetInnerText(labelText);
63:
64: TagBuilder input = new TagBuilder("input");
65: input.GenerateId(id);
66: input.MergeAttribute("name", name);
67: input.MergeAttribute("type", "radio");
68: input.MergeAttribute("value", value);
69: input.MergeAttributes(htmlAttributes);
70: if (isChecked)
71: {
72: input.MergeAttribute("checked", "checked");
73: }
74: sb.AppendLine(input.ToString());
75: sb.AppendLine(label.ToString());
76: return sb.ToString();
77: }
78: }
- SpringMVC返回图片的几种方式
- Redis实现分布式锁相关注意事项
- React Native调用Android相机图库
- SpringMVC之请求参数的获取方式
- 糖大夫--测量流程性能监控自动化方案设计
- ReactNative调用Android原生模块
- jvm调优的工具介绍
- Python时间序列预测案例研究:巴尔的摩年度用水量
- [一对一课程] 之 设计并实现第一个JS模块?
- React Native 使用react-native-image-picker库实现图片上传功能
- 再谈Android动态链接库
- React Native之Permissions权限适配
- React Native项目实战之fetch请求并填充界面
- CocoaPods使用详解
- HTML 教程
- HTML 简介
- html div 标签介绍
- html span 标签介绍
- html a 超链接标签
- HTML Br换行标签介绍
- HTML P段落标签介绍
- HTML br与p标签区别
- Html H 标题标签
- html px em pt长度单位
- HTML form 标签
- HTML radio 单选框
- HTML B 加粗标签
- HTML strong加粗粗体标签
- HTML em 强调标签
- HTML i 斜体标签
- HTML u下划线标签
- HTML s 删除线标签
- Html img 图片标签
- Html上标注sup与下标注sub标签
- HTML nobr 禁止换行标签
- HTML hr 水平线标签
- HTML label 标签
- HTML input 标签
- HTML textarea 标签
- HTML select下拉列表标签
- HTML checkbox 多选框
- HTML font color 标签
- HTML iframe 框架标签
- HTML Table 表格
- HTML dl dt dd 标签
- HTML ol li有序列表标签
- HTML ul li 无序列表标签
- HTML 注释
- CSS 教程
- CSS 简介
- CSS 语法
- CSS Id 和 Class选择器
- CSS 样式的创建
- CSS background 背景介绍
- CSS 文本样式
- CSS font 字体
- CSS A 链接
- CSS ul ol列表样式
- CSS TABLE 样式
- CSS 框模型
- CSS border 边框
- CSS Outlines 轮廓
- CSS 外边距 Margin
- CSS Padding 内边距
- CSS 分组和嵌套选择器
- CSS 尺寸 (Dimension)
- CSS Display 属性
- CSS Position 定位
- CSS Float 浮动
- CSS 水平对齐(Horizontal Align)
- CSS 组合选择符
- CSS 伪类
- CSS 伪元素
- CSS 导航栏
- CSS 下拉菜单
- CSS 图片廊
- CSS 图像透明/不透明
- CSS sprite 图像拼合技术
- CSS 媒体类型
- CSS 属性选择器
- CSS 实例
- Laravel 微信小程序后端搭建步骤详解
- Laravel使用swoole实现websocket主动消息推送的方法介绍
- Laravel框架Eloquent ORM删除数据操作示例
- PHP常用函数之base64图片上传功能详解
- laravel-admin 实现在指定的相册下添加照片
- Laravel框架Eloquent ORM修改数据操作示例
- PHP常用函数之格式化时间操作示例
- 在phpstudy集成环境下的nginx服务器下配置url重写
- 关于laravel-admin ueditor 集成并解决刷新的问题
- PHP常用函数之根据生日计算年龄功能示例
- Laravel 之url参数,获取路由参数的例子
- PHP call_user_func和call_user_func_array函数的简单理解与应用分析
- PHP常用函数之获取汉字首字母功能示例
- 浅谈laravel-admin form中的数据,在提交后,保存前,获取并进行编辑
- tp5 实现列表数据根据状态排序