2012年9月24日 星期一

ASP.NET MVC - 修改 CheckBoxList、增加 RadioButtonList


在今年初我有發表一篇有關於可以水平、垂直顯示的 CheckBoxList Extensions,其實這個 Html Helper Extensions 是沒有什麼問題,「ASP.NET MVC 擴充HtmlHelper 加入 CheckBoxList 功能 - 2」,前不久在看 DropDownList() 原始碼時想到,為什麼不直接使用既有的 SelectListItem 呢?實在是沒有必要另外去建立一個相同結構的 CheckBoxListInfo 類別,所以這次就做個小修改,捨棄原先的 CheckBoxListInfo 類別而改使用既有 SelectListItem 類別,而既然 CheckBoxList 都已經做出來了,那長得差不多的 RadioButtonList 也就動手做了出來,以下就是這兩個 Html Helper Extensions 的介紹。

 


基本使用:

先來看看 CheckBoxList 與 RadioButtonList 的執行結果,

image

CheckBoxList 與 RadioButtonList 都同樣的顯示了水平與垂直顯示的列表,水平列表是每個橫列都顯示兩個項目,垂直列表則都是顯示三個直行。

 

接下來看看 Controller Action() 方法的程式內容:

從資料庫取出產品分類的資料,然後建立 List<SelectListItem> 集合物件,接著再把 items 物件給放到 ViewBag 之中,等一下前端 View 設定時可以使用到。

image

 

View 的設定:

使用 Position.Horizontal 時,最後的數值參數是用來決定每個橫列要顯示多少個項目數量,使用 Position.Vertical 時,最後的數值參數則是用來決定要顯示多少直行數,

image

 

 

設定預設選項:

這邊設定預設選項的方式與設定下拉選單預選項目的方式是一樣的,將 SelectListItem 的 Selctedn 設定為 true 就可以,CheckBoxList 是可以設定多個項目為選擇狀態,至於 RadioButtonList 則是與 DropDownList 一樣為單選。

 

先看看 CheckBoxList 的內容,

Controller:

這裡是讓 CategoryID 為偶數的項目設定為與選項目

image

 

View:

View 這邊的設定並不需要去做任何的變動

image

 

執行結果:

image

 

RadioButtonList 的內容,

因為 RadioButtonList 跟 DropDownList 一樣是屬於單選的列表,所以如果是拿上面 Controller 的設定內容來使用的話,並不會有多個 RadioButton 被選取的情況發生,只有最後一個 Selected == true 的 SelectListItem 是會被選取的,

Controller:

image

View:

image

執行結果:

image

 

 

使用 SelectList

當然除了使用 IEnumerable<SelectListItem> 之外,也是一樣可以使用 SelectList 類別,在之前討論 DropDownList 基本設定的文章當中就已經有說過 SelectList 的父類別 MultiSelectList 就是繼承自 IEnumerable<SelectListItem>,所以當然可以使用 SelectList。

 

Controller:

image

View:

image

執行結果:

image

 


CheckBoxList & RadioButtonList 原始檔

這邊公布原始檔的程式內容,請各位自行做適當的修改後再加入到自己的 ASP.NET MVC 專案中,經過測試,於 ASP.NET MVC 3.0 與 ASP.NET MVC 4.0 的網站專案中都可以正常執行。

image

 

Position.cs

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Web;
   5:  
   6: namespace MvcApplication.Helpers
   7: {
   8:     public enum Position
   9:     {
  10:         Horizontal,
  11:         Vertical
  12:     }
  13: }

 

CheckBoxListExtensions.cs

image

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Web.Mvc;
   6: using System.Web.Routing;
   7:  
   8: namespace MvcApplication.Helpers
   9: {
  10:     public static class CheckBoxListExtensions
  11:     {
  12:         #region -- CheckBoxList (Horizontal) --
  13:         /// <summary>
  14:         /// CheckBoxList.
  15:         /// </summary>
  16:         /// <param name="htmlHelper">The HTML helper.</param>
  17:         /// <param name="name">The name.</param>
  18:         /// <param name="listInfo">SelectListItem.</param>
  19:         /// <returns></returns>
  20:         public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, 
  21:             string name, 
  22:             IEnumerable<SelectListItem> listInfo)
  23:         {
  24:             return htmlHelper.CheckBoxList(name, listInfo, (IDictionary<string, object>)null, 0);
  25:         }
  26:  
  27:         /// <summary>
  28:         /// CheckBoxList.
  29:         /// </summary>
  30:         /// <param name="htmlHelper">The HTML helper.</param>
  31:         /// <param name="name">The name.</param>
  32:         /// <param name="listInfo">SelectListItem.</param>
  33:         /// <param name="htmlAttributes">The HTML attributes.</param>
  34:         /// <returns></returns>
  35:         public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, 
  36:             string name, 
  37:             IEnumerable<SelectListItem> listInfo, 
  38:             object htmlAttributes)
  39:         {
  40:             return htmlHelper.CheckBoxList(name, listInfo, (IDictionary<string, object>)new RouteValueDictionary(htmlAttributes), 0);
  41:         }
  42:  
  43:         /// <summary>
  44:         /// CheckBoxList.
  45:         /// </summary>
  46:         /// <param name="htmlHelper">The HTML helper.</param>
  47:         /// <param name="name">The name.</param>
  48:         /// <param name="listInfo">The list info.</param>
  49:         /// <param name="htmlAttributes">The HTML attributes.</param>
  50:         /// <param name="number">每個Row的顯示個數.</param>
  51:         /// <returns></returns>
  52:         public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper,
  53:             string name,
  54:             IEnumerable<SelectListItem> listInfo,
  55:             IDictionary<string, object> htmlAttributes,
  56:             int number)
  57:         {
  58:             if (String.IsNullOrEmpty(name))
  59:             {
  60:                 throw new ArgumentException("必須給這些CheckBoxList一個Tag Name", "name");
  61:             }
  62:             if (listInfo == null)
  63:             {
  64:                 throw new ArgumentNullException("listInfo", "必須要給List<SelectListItem> listInfo");
  65:             }
  66:             if (listInfo.Count() < 1)
  67:             {
  68:                 throw new ArgumentException("List<SelectListItem> listInfo 至少要有一組資料", "listInfo");
  69:             }
  70:  
  71:             StringBuilder sb = new StringBuilder();
  72:             int lineNumber = 0;
  73:  
  74:             foreach (SelectListItem info in listInfo)
  75:             {
  76:                 lineNumber++;
  77:  
  78:                 TagBuilder builder = new TagBuilder("input");
  79:                 if (info.Selected)
  80:                 {
  81:                     builder.MergeAttribute("checked", "checked");
  82:                 }
  83:                 builder.MergeAttributes<string, object>(htmlAttributes);
  84:                 builder.MergeAttribute("type", "checkbox");
  85:                 builder.MergeAttribute("value", info.Value);
  86:                 builder.MergeAttribute("name", name);
  87:                 sb.Append(builder.ToString(TagRenderMode.Normal));
  88:  
  89:                 TagBuilder labelBuilder = new TagBuilder("label");
  90:                 labelBuilder.MergeAttribute("for", name);
  91:                 labelBuilder.InnerHtml = info.Text;
  92:                 sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
  93:  
  94:                 if (number == 0 || (lineNumber % number == 0))
  95:                 {
  96:                     sb.Append("<br />");
  97:                 }
  98:             }
  99:             return MvcHtmlString.Create(sb.ToString());
 100:         }
 101:         #endregion
 102:  
 103:         #region -- CheckBoxListVertical --
 104:         /// <summary>
 105:         /// Checks the box list vertical.
 106:         /// </summary>
 107:         /// <param name="htmlHelper">The HTML helper.</param>
 108:         /// <param name="name">The name.</param>
 109:         /// <param name="listInfo">The list info.</param>
 110:         /// <param name="htmlAttributes">The HTML attributes.</param>
 111:         /// <param name="columnNumber">The column number.</param>
 112:         /// <returns></returns>
 113:         public static MvcHtmlString CheckBoxListVertical(this HtmlHelper htmlHelper,
 114:             string name,
 115:             IEnumerable<SelectListItem> listInfo,
 116:             IDictionary<string, object> htmlAttributes,
 117:             int columnNumber = 1)
 118:         {
 119:             if (String.IsNullOrEmpty(name))
 120:             {
 121:                 throw new ArgumentException("必須給這些CheckBoxList一個Tag Name", "name");
 122:             }
 123:             if (listInfo == null)
 124:             {
 125:                 throw new ArgumentNullException("listInfo", "必須要給List<CheckBoxListInfo> listInfo");
 126:             }
 127:             if (listInfo.Count() < 1)
 128:             {
 129:                 throw new ArgumentException("List<CheckBoxListInfo> listInfo 至少要有一組資料", "listInfo");
 130:             }
 131:  
 132:             int dataCount = listInfo.Count();
 133:  
 134:             // calculate number of rows
 135:             int rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount) / Convert.ToDecimal(columnNumber)));
 136:             if (dataCount <= columnNumber || dataCount - columnNumber == 1)
 137:             {
 138:                 rows = dataCount;
 139:             }
 140:  
 141:             TagBuilder wrapBuilder = new TagBuilder("div");
 142:             wrapBuilder.MergeAttribute("style", "float: left; light-height: 25px; padding-right: 5px;");
 143:  
 144:             string wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
 145:             string wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag), " <div style=\"clear:both;\"></div>");
 146:             string wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
 147:  
 148:             StringBuilder sb = new StringBuilder();
 149:             sb.Append(wrapStart);
 150:  
 151:             int lineNumber = 0;
 152:  
 153:             foreach (var info in listInfo)
 154:             {
 155:                 TagBuilder builder = new TagBuilder("input");
 156:                 if (info.Selected)
 157:                 {
 158:                     builder.MergeAttribute("checked", "checked");
 159:                 }
 160:                 builder.MergeAttributes<string, object>(htmlAttributes);
 161:                 builder.MergeAttribute("type", "checkbox");
 162:                 builder.MergeAttribute("value", info.Value);
 163:                 builder.MergeAttribute("name", name);
 164:                 sb.Append(builder.ToString(TagRenderMode.Normal));
 165:  
 166:                 TagBuilder labelBuilder = new TagBuilder("label");
 167:                 labelBuilder.MergeAttribute("for", name);
 168:                 labelBuilder.InnerHtml = info.Text;
 169:                 sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 170:  
 171:                 lineNumber++;
 172:  
 173:                 if (lineNumber.Equals(rows))
 174:                 {
 175:                     sb.Append(wrapBreak);
 176:                     lineNumber = 0;
 177:                 }
 178:                 else
 179:                 {
 180:                     sb.Append("<br/>");
 181:                 }
 182:             }
 183:             sb.Append(wrapClose);
 184:             return MvcHtmlString.Create(sb.ToString());
 185:         }
 186:         #endregion
 187:  
 188:         #region -- CheckBoxList (Horizonal, Vertical) --
 189:         /// <summary>
 190:         /// Checks the box list.
 191:         /// </summary>
 192:         /// <param name="htmlHelper">The HTML helper.</param>
 193:         /// <param name="name">The name.</param>
 194:         /// <param name="listInfo">The list info.</param>
 195:         /// <param name="htmlAttributes">The HTML attributes.</param>
 196:         /// <param name="position">The position.</param>
 197:         /// <param name="number">Position.Horizontal則表示每個Row的顯示個數, Position.Vertical則表示要顯示幾個Column</param>
 198:         /// <returns></returns>
 199:         public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper,
 200:             string name,
 201:             IEnumerable<SelectListItem> listInfo,
 202:             IDictionary<string, object> htmlAttributes,
 203:             Position position = Position.Horizontal,
 204:             int number = 0)
 205:         {
 206:             if (String.IsNullOrEmpty(name))
 207:             {
 208:                 throw new ArgumentException("必須給這些CheckBoxList一個Tag Name", "name");
 209:             }
 210:             if (listInfo == null)
 211:             {
 212:                 throw new ArgumentNullException("listInfo", "必須要給List<SelectListItem> listInfo");
 213:             }
 214:             if (listInfo.Count() < 1)
 215:             {
 216:                 throw new ArgumentException("List<SelectListItem> listInfo 至少要有一組資料", "listInfo");
 217:             }
 218:  
 219:             StringBuilder sb = new StringBuilder();
 220:             int lineNumber = 0;
 221:  
 222:             switch (position)
 223:             {
 224:                 case Position.Horizontal:
 225:  
 226:                     foreach (SelectListItem info in listInfo)
 227:                     {
 228:                         lineNumber++;
 229:                         sb.Append(CreateCheckBoxItem(info, name, htmlAttributes));
 230:  
 231:                         if (number == 0 || (lineNumber % number == 0))
 232:                         {
 233:                             sb.Append("<br />");
 234:                         }
 235:                     }
 236:                     break;
 237:  
 238:                 case Position.Vertical:
 239:  
 240:                     int dataCount = listInfo.Count();
 241:  
 242:                     // 計算最大顯示的列數(rows)
 243:                     int rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount) / Convert.ToDecimal(number)));
 244:                     if (dataCount <= number || dataCount - number == 1)
 245:                     {
 246:                         rows = dataCount;
 247:                     }
 248:  
 249:                     TagBuilder wrapBuilder = new TagBuilder("div");
 250:                     wrapBuilder.MergeAttribute("style", "float: left; light-height: 25px; padding-right: 5px;");
 251:  
 252:                     string wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
 253:                     string wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag), " <div style=\"clear:both;\"></div>");
 254:                     string wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
 255:  
 256:                     sb.Append(wrapStart);
 257:  
 258:                     foreach (SelectListItem info in listInfo)
 259:                     {
 260:                         lineNumber++;
 261:                         sb.Append(CreateCheckBoxItem(info, name, htmlAttributes));
 262:  
 263:                         if (lineNumber.Equals(rows))
 264:                         {
 265:                             sb.Append(wrapBreak);
 266:                             lineNumber = 0;
 267:                         }
 268:                         else
 269:                         {
 270:                             sb.Append("<br/>");
 271:                         }
 272:                     }
 273:                     sb.Append(wrapClose);
 274:                     break;
 275:             }
 276:  
 277:             return MvcHtmlString.Create(sb.ToString());
 278:         }
 279:  
 280:         internal static string CreateCheckBoxItem(SelectListItem info, string name, IDictionary<string, object> htmlAttributes)
 281:         {
 282:             StringBuilder sb = new StringBuilder();
 283:  
 284:             TagBuilder builder = new TagBuilder("input");
 285:             if (info.Selected)
 286:             {
 287:                 builder.MergeAttribute("checked", "checked");
 288:             }
 289:             builder.MergeAttributes<string, object>(htmlAttributes);
 290:             builder.MergeAttribute("type", "checkbox");
 291:             builder.MergeAttribute("value", info.Value);
 292:             builder.MergeAttribute("name", name);
 293:             sb.Append(builder.ToString(TagRenderMode.Normal));
 294:  
 295:             TagBuilder labelBuilder = new TagBuilder("label");
 296:             labelBuilder.MergeAttribute("for", name);
 297:             labelBuilder.InnerHtml = info.Text;
 298:             sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 299:  
 300:             return sb.ToString();
 301:         }
 302:         #endregion
 303:     }
 304: }

 

RadioButtonListExtensions.cs

image

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Linq;
   4: using System.Text;
   5: using System.Web.Mvc;
   6: using System.Web.Routing;
   7:  
   8: namespace MvcApplication.Helpers
   9: {
  10:     public static class RadioButtonListExtensions
  11:     {
  12:         #region -- RadioButtonList (Horizontal) --
  13:         /// <summary>
  14:         /// RadioButtonList.
  15:         /// </summary>
  16:         /// <param name="htmlHelper">The HTML helper.</param>
  17:         /// <param name="name">The name.</param>
  18:         /// <param name="listInfo">RadioButtonListInfo.</param>
  19:         /// <returns></returns>
  20:         public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, 
  21:             string name, 
  22:             IEnumerable<SelectListItem> listInfo)
  23:         {
  24:             return htmlHelper.RadioButtonList(name, listInfo, (IDictionary<string, object>)null, 0);
  25:         }
  26:  
  27:         /// <summary>
  28:         /// RadioButtonList.
  29:         /// </summary>
  30:         /// <param name="htmlHelper">The HTML helper.</param>
  31:         /// <param name="name">The name.</param>
  32:         /// <param name="listInfo">RadioButtonListInfo.</param>
  33:         /// <param name="htmlAttributes">The HTML attributes.</param>
  34:         /// <returns></returns>
  35:         public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper, 
  36:             string name,
  37:             IEnumerable<SelectListItem> listInfo, 
  38:             object htmlAttributes)
  39:         {
  40:             return htmlHelper.RadioButtonList(
  41:                 name, 
  42:                 listInfo, 
  43:                 (IDictionary<string, object>)new RouteValueDictionary(htmlAttributes), 
  44:                 0);
  45:         }
  46:  
  47:         /// <summary>
  48:         /// RadioButtonList.
  49:         /// </summary>
  50:         /// <param name="htmlHelper">The HTML helper.</param>
  51:         /// <param name="name">The name.</param>
  52:         /// <param name="listInfo">The list info.</param>
  53:         /// <param name="htmlAttributes">The HTML attributes.</param>
  54:         /// <param name="number">每個Row的顯示個數.</param>
  55:         /// <returns></returns>
  56:         public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper,
  57:             string name,
  58:             IEnumerable<SelectListItem> listInfo,
  59:             IDictionary<string, object> htmlAttributes,
  60:             int number)
  61:         {
  62:             if (String.IsNullOrEmpty(name))
  63:             {
  64:                 throw new ArgumentException("必須給這些RadioButtonList一個Tag Name", "name");
  65:             }
  66:             if (listInfo == null)
  67:             {
  68:                 throw new ArgumentNullException("listInfo", "必須要給List<RadioButtonListInfo> listInfo");
  69:             }
  70:             if (listInfo.Count() < 1)
  71:             {
  72:                 throw new ArgumentException("List<RadioButtonListInfo> listInfo 至少要有一組資料", "listInfo");
  73:             }
  74:  
  75:             StringBuilder sb = new StringBuilder();
  76:             int lineNumber = 0;
  77:  
  78:             foreach (SelectListItem info in listInfo)
  79:             {
  80:                 lineNumber++;
  81:  
  82:                 TagBuilder builder = new TagBuilder("input");
  83:                 if (info.Selected)
  84:                 {
  85:                     builder.MergeAttribute("checked", "checked");
  86:                 }
  87:                 builder.MergeAttributes<string, object>(htmlAttributes);
  88:                 builder.MergeAttribute("type", "radio");
  89:                 builder.MergeAttribute("value", info.Value);
  90:                 builder.MergeAttribute("name", name);
  91:                 sb.Append(builder.ToString(TagRenderMode.Normal));
  92:  
  93:                 TagBuilder labelBuilder = new TagBuilder("label");
  94:                 labelBuilder.MergeAttribute("for", name);
  95:                 labelBuilder.InnerHtml = info.Text;
  96:                 sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
  97:  
  98:                 if (number == 0 || (lineNumber % number == 0))
  99:                 {
 100:                     sb.Append("<br />");
 101:                 }
 102:             }
 103:             return MvcHtmlString.Create(sb.ToString());
 104:         }
 105:         #endregion
 106:  
 107:         #region -- RadioButtonVertical --
 108:         /// <summary>
 109:         /// Checks the box list vertical.
 110:         /// </summary>
 111:         /// <param name="htmlHelper">The HTML helper.</param>
 112:         /// <param name="name">The name.</param>
 113:         /// <param name="listInfo">The list info.</param>
 114:         /// <param name="htmlAttributes">The HTML attributes.</param>
 115:         /// <param name="columnNumber">The column number.</param>
 116:         /// <returns></returns>
 117:         public static MvcHtmlString RadioButtonVertical(this HtmlHelper htmlHelper,
 118:             string name,
 119:             IEnumerable<SelectListItem> listInfo,
 120:             IDictionary<string, object> htmlAttributes,
 121:             int columnNumber = 1)
 122:         {
 123:             if (String.IsNullOrEmpty(name))
 124:             {
 125:                 throw new ArgumentException("必須給這些RadioButton一個Tag Name", "name");
 126:             }
 127:             if (listInfo == null)
 128:             {
 129:                 throw new ArgumentNullException("listInfo", "必須要給List<RadioButtonInfo> listInfo");
 130:             }
 131:             if (listInfo.Count() < 1)
 132:             {
 133:                 throw new ArgumentException("List<RadioButtonInfo> listInfo 至少要有一組資料", "listInfo");
 134:             }
 135:  
 136:             int dataCount = listInfo.Count();
 137:  
 138:             // calculate number of rows
 139:             int rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount) / Convert.ToDecimal(columnNumber)));
 140:             if (dataCount <= columnNumber || dataCount - columnNumber == 1)
 141:             {
 142:                 rows = dataCount;
 143:             }
 144:  
 145:             TagBuilder wrapBuilder = new TagBuilder("div");
 146:             wrapBuilder.MergeAttribute("style", "float: left; light-height: 25px; padding-right: 5px;");
 147:  
 148:             string wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
 149:             string wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag), " <div style=\"clear:both;\"></div>");
 150:             string wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
 151:  
 152:             StringBuilder sb = new StringBuilder();
 153:             sb.Append(wrapStart);
 154:  
 155:             int lineNumber = 0;
 156:  
 157:             foreach (var info in listInfo)
 158:             {
 159:                 TagBuilder builder = new TagBuilder("input");
 160:                 if (info.Selected)
 161:                 {
 162:                     builder.MergeAttribute("checked", "checked");
 163:                 }
 164:                 builder.MergeAttributes<string, object>(htmlAttributes);
 165:                 builder.MergeAttribute("type", "radio");
 166:                 builder.MergeAttribute("value", info.Value);
 167:                 builder.MergeAttribute("name", name);
 168:                 sb.Append(builder.ToString(TagRenderMode.Normal));
 169:  
 170:                 TagBuilder labelBuilder = new TagBuilder("label");
 171:                 labelBuilder.MergeAttribute("for", name);
 172:                 labelBuilder.InnerHtml = info.Text;
 173:                 sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 174:  
 175:                 lineNumber++;
 176:  
 177:                 if (lineNumber.Equals(rows))
 178:                 {
 179:                     sb.Append(wrapBreak);
 180:                     lineNumber = 0;
 181:                 }
 182:                 else
 183:                 {
 184:                     sb.Append("<br/>");
 185:                 }
 186:             }
 187:             sb.Append(wrapClose);
 188:             return MvcHtmlString.Create(sb.ToString());
 189:         }
 190:         #endregion
 191:  
 192:         #region -- RadioButtonList (Horizonal, Vertical) --
 193:         /// <summary>
 194:         /// Checks the box list.
 195:         /// </summary>
 196:         /// <param name="htmlHelper">The HTML helper.</param>
 197:         /// <param name="name">The name.</param>
 198:         /// <param name="listInfo">The list info.</param>
 199:         /// <param name="htmlAttributes">The HTML attributes.</param>
 200:         /// <param name="position">The position.</param>
 201:         /// <param name="number">Position.Horizontal則表示每個Row的顯示個數, Position.Vertical則表示要顯示幾個Column</param>
 202:         /// <returns></returns>
 203:         public static MvcHtmlString RadioButtonList(this HtmlHelper htmlHelper,
 204:             string name,
 205:             IEnumerable<SelectListItem> listInfo,
 206:             IDictionary<string, object> htmlAttributes,
 207:             Position position = Position.Horizontal,
 208:             int number = 0)
 209:         {
 210:             if (String.IsNullOrEmpty(name))
 211:             {
 212:                 throw new ArgumentException("必須給這些RadioButtonList一個Tag Name", "name");
 213:             }
 214:             if (listInfo == null)
 215:             {
 216:                 throw new ArgumentNullException("listInfo", "必須要給List<RadioButtonListInfo> listInfo");
 217:             }
 218:             if (listInfo.Count() < 1)
 219:             {
 220:                 throw new ArgumentException("List<RadioButtonListInfo> listInfo 至少要有一組資料", "listInfo");
 221:             }
 222:  
 223:             StringBuilder sb = new StringBuilder();
 224:             int lineNumber = 0;
 225:  
 226:             switch (position)
 227:             {
 228:                 case Position.Horizontal:
 229:  
 230:                     foreach (SelectListItem info in listInfo)
 231:                     {
 232:                         lineNumber++;
 233:                         sb.Append(CreateRadioButtonItem(info, name, htmlAttributes));
 234:  
 235:                         if (number == 0 || (lineNumber % number == 0))
 236:                         {
 237:                             sb.Append("<br />");
 238:                         }
 239:                     }
 240:                     break;
 241:  
 242:                 case Position.Vertical:
 243:  
 244:                     int dataCount = listInfo.Count();
 245:  
 246:                     // 計算最大顯示的列數(rows)
 247:                     int rows = Convert.ToInt32(Math.Ceiling(Convert.ToDecimal(dataCount) / Convert.ToDecimal(number)));
 248:                     if (dataCount <= number || dataCount - number == 1)
 249:                     {
 250:                         rows = dataCount;
 251:                     }
 252:  
 253:                     TagBuilder wrapBuilder = new TagBuilder("div");
 254:                     wrapBuilder.MergeAttribute("style", "float: left; light-height: 25px; padding-right: 5px;");
 255:  
 256:                     string wrapStart = wrapBuilder.ToString(TagRenderMode.StartTag);
 257:                     string wrapClose = string.Concat(wrapBuilder.ToString(TagRenderMode.EndTag), " <div style=\"clear:both;\"></div>");
 258:                     string wrapBreak = string.Concat("</div>", wrapBuilder.ToString(TagRenderMode.StartTag));
 259:  
 260:                     sb.Append(wrapStart);
 261:  
 262:                     foreach (SelectListItem info in listInfo)
 263:                     {
 264:                         lineNumber++;
 265:                         sb.Append(CreateRadioButtonItem(info, name, htmlAttributes));
 266:  
 267:                         if (lineNumber.Equals(rows))
 268:                         {
 269:                             sb.Append(wrapBreak);
 270:                             lineNumber = 0;
 271:                         }
 272:                         else
 273:                         {
 274:                             sb.Append("<br/>");
 275:                         }
 276:                     }
 277:                     sb.Append(wrapClose);
 278:                     break;
 279:             }
 280:  
 281:             return MvcHtmlString.Create(sb.ToString());
 282:         }
 283:  
 284:         /// <summary>
 285:         /// CreateRadioButtonItem
 286:         /// </summary>
 287:         /// <param name="info"></param>
 288:         /// <param name="name"></param>
 289:         /// <param name="htmlAttributes"></param>
 290:         /// <returns></returns>
 291:         internal static string CreateRadioButtonItem(
 292:             SelectListItem info, 
 293:             string name, 
 294:             IDictionary<string, object> htmlAttributes)
 295:         {
 296:             StringBuilder sb = new StringBuilder();
 297:  
 298:             TagBuilder builder = new TagBuilder("input");
 299:             if (info.Selected)
 300:             {
 301:                 builder.MergeAttribute("checked", "checked");
 302:             }
 303:             builder.MergeAttributes<string, object>(htmlAttributes);
 304:             builder.MergeAttribute("type", "radio");
 305:             builder.MergeAttribute("value", info.Value);
 306:             builder.MergeAttribute("name", name);
 307:             sb.Append(builder.ToString(TagRenderMode.Normal));
 308:  
 309:             TagBuilder labelBuilder = new TagBuilder("label");
 310:             labelBuilder.MergeAttribute("for", name);
 311:             labelBuilder.InnerHtml = info.Text;
 312:             sb.Append(labelBuilder.ToString(TagRenderMode.Normal));
 313:  
 314:             return sb.ToString();
 315:         }
 316:         #endregion
 317:     }
 318: }

 

2012-09-28 更新:

之前所提供的「RadioButtonListExtensions」程式碼,上一個版本我把「RadioButtonList」打錯字了!!!

錯的字「RadioButtinList」… 正確的「RadioButtonList」…

至於上面有圖片內容還是使用「RadioButtinList」就算了,不想重新擷圖,所以請各位看到就自動取代替換吧。

 


補充說明

這一次的範例說明網站是用預設的 ASP.NET MVC 4 網站專案範本,如果沒有對預設網站的 CSS 做調整的話,直接使用我所提供的 CheckBoxList or RadioButtonList 於顯示時會怪怪的,

image

並不是我提供的 Html Helper Extensions 有問題或是 Bug,這只是 CSS 的設定不同所導致的,可以對 Content / Site.css 內容的兩個地方做點修改就可以正常顯示了,

image

image


以上

15 則留言:

  1. 您好
    您原本的code 產生出來的CheckBox不能點label就勾選CheckBox
    在TagBuilder 部分加上各自加上 下面code 就可以達到點label就勾選CheckBox
    labelBuilder.MergeAttribute("for", name + info.Value);
    CheckBoxbuilder.MergeAttribute("id", name + info.Value);

    感謝您 提供 複選欄位的 解法

    回覆刪除
  2. how do i reference
    a helper folder

    回覆刪除
    回覆
    1. create a [helper] folder, add 3 *.cs files and copy the code, change Namespace(recommand)
      (Position.cs, CheckBoxListExtensions.cs, RadioButtonListExtensions.cs)






      刪除
  3. 假如我把(Produce和Dairy Products和Seafood)這三個值勾選起來,
    存到db裡面,而且是在同一張資料表同一個欄位,
    值為(Produce,Dairy Products,Seafood)的話,
    要如何把這三個呈現出是已勾選,其他的是未勾選。

    回覆刪除
    回覆
    1. 可以在後端組成 List 或是 SelectList 的時候就做判斷,
      我假設你有將勾選的項目給儲存到資料庫裡,
      那個在後端組成 List 或是 SelectList 的時候,就已經把選項從資料庫抓出來,
      那麼再把你所儲存的選項目抓出來,然後每個項目去比對是否勾選,
      如果有勾選,則該選項的 selected 為 true,反之為 false,
      這種 SelectListItem 操作與 DropDownList 的操作是一樣的,
      可參考「ASP.NET MVC 3 - DropDownList 的基本設定方式」
      http://kevintsengtw.blogspot.tw/2012/09/aspnet-mvc-3-dropdownlist.html

      刪除
    2. 我是用兩張資料表,一張是存全部的產品類別,另一張是存產品的資料。
      而存產品資料的資料表裡面有一欄是存勾選的產品類別,所以不是只用一張資料表。
      我沒解釋清楚@@

      刪除
    3. Hello, 一樣的作法,既然你是在某個 table 的欄位中存放勾選的資料,
      假設你所存的勾選資料是存產品資料的 id, 並且是以「,」分隔,
      那麼在判斷產品項目是否有勾選的時候,就可以把所存的勾選資料給抓出來,
      然後建立 SelectListItem 的 List 時就可以做判斷。
      做法跟我上面所回覆你的是一樣的,你先試著去實作。

      刪除
    4. 一圖勝千文,
      https://dl.dropboxusercontent.com/u/26764200/images/blog/20130715_1506.jpg

      刪除
  4. 原本的我是用兩層的foreach來執行迴圈,第二層裡面用if else判斷,造成會出現重覆的核取項出現。(讓我的頭殼卡了三天)
    原來只要用一層就出現了,然後是在selected判斷,我還以為是用if else來做,
    真的太好了,感激中!!!!

    回覆刪除
    回覆
    1. 有時候程式的問題都只是一個小環節而形成的,通了就解了。

      刪除
  5. 不好意思,想請教您
    若是使用這個checkboxlist的helper,我該如何跟ValidationMessage搭配使用呢?

    回覆刪除
    回覆
    1. 你好,可以參考以下兩篇文章
      .
      ASP.NET MVC - CheckBoxList 與 ValidationMessage (ASP.NET MVC 5 with Bootstrap3)
      http://goo.gl/juJwS0
      .
      ASP.NET MVC - CheckBoxList 與 ValidationMessage (ASP.NET MVC 4 without Bootstrap)
      http://goo.gl/43bH7f

      刪除
  6. Hi,
    How to get selected values in controller for both the controls

    回覆刪除
    回覆
    1. Hello, avinash
      Every Checkbox has same Name,
      so, in Controller's Action method, add parameter use same name,
      ex: CheckBoxList Name use [cities], action's parameter name must use [cities]
      that we can get selected values in Controller.

      刪除

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。