[ASP.NET MVC]為HtmlHelper添加一個RadioButtonList擴展方法
在前麵一篇文章中,我們通過對HtmlHelper的擴展簡化了對DropDownList(Single-Line-Select)和ListBox(Multiple-Line-Select)的綁定,以及對作為數據源的列表進行單獨維護。現在我們為HtmlHelper/HtmlHelper<Model>添加一個RadioButtonList/RadioButtonListFor擴展方法實現一組RadioButton的綁定。[源代碼從這裏下載]
我們先來顯示一下擴展的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: }
由於在一個應用中,作為綁定到“列表控件”上的選項列表可能會有很多,將它們進行單獨地維護是一個理想的選擇。作為模擬,我們創建了如下一個簡單的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兩個擴展方法的定義,參數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: }
通過對HtmlHelper擴展簡化“列表控件”的綁定
為HtmlHelper添加一個RadioButtonList擴展方法
在ASP.NET MVC中使用“RadioButtonList”和“CheckBoxList”
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-26 12:04:24