MVC若要使用Radio Button,預設的HtmlHelper只有RadioButtonFor方法可以使用,這是單一個Radio Button,所以若要呈現5個按鈕就要呼叫5次,或使用迴圈巡覽資料集來叫用。而針對顯示的文字及Html也須另外撰寫。針對這種寫了會令人在維護時眼花瞭亂的程式,最好的方式還是寫了一個Helper來解決。
改善前的作法
@foreach (var item in DataUtility.GetDatas())
{
<label class="radio">
@Html.RadioButtonFor(model => model.ProductId, item.ProductId)
@Html.DisplayFor(model => item.ProductName)
</label>
}
改善後的作法
1.針對上方的程式透過Helper的擴充,包成一個方法
/// <summary>
/// RadioButtonList for 資料集
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="helper"></param>
/// <param name="items">資料集</param>
/// <param name="dataValueField">值欄位</param>
/// <param name="dataTextField">顯示欄位</param>
/// <param name="expression"></param>
/// <param name="htmlAttributes"></param>
/// <param name="appendOptionLabel">是否增加預設選項 例:請選擇</param>
/// <param name="optionLabel">預設選項文字</param>
/// <param name="direction">顯示方向:垂直、水平</param>
/// <returns></returns>
public static MvcHtmlString RadioButtonListForList<T, TProperty>(this HtmlHelper<T> helper
, IEnumerable items, string dataValueField, string dataTextField, Expression<Func<T, TProperty>> expression
, object htmlAttributes = null, bool appendOptionLabel = false, string optionLabel = null
, RepeatDirections direction = RepeatDirections.Horizontal)
{
string name = BuildColumnNameFromModel(expression);
var optionData = from object o in items
select new KeyValuePair<string, string>(Eval(o, dataTextField), Eval(o, dataValueField));
string defaultSelectValue = helper.ViewData.Eval(name).ToString();
return BuildRadioButtonList(helper, expression, name, defaultSelectValue, optionData, htmlAttributes, appendOptionLabel, optionLabel, direction);
}
2.同場加映列舉轉成RadioButtonList方法
/// <summary>
/// RadioButtonList for 列舉
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="helper"></param>
/// <param name="expression"></param>
/// <param name="htmlAttributes"></param>
/// <param name="appendOptionLabel">是否增加預設選項 例:請選擇</param>
/// <param name="optionLabel">預設選項文字</param>
/// <param name="direction">顯示方向:垂直、水平</param>
/// <returns></returns>
public static MvcHtmlString RadioButtonListForEnum<T, TProperty>(this HtmlHelper<T> helper
, Expression<Func<T, TProperty>> expression
, object htmlAttributes = null, bool appendOptionLabel = false, string optionLabel = null
, RepeatDirections direction = RepeatDirections.Horizontal)
{
string name = BuildColumnNameFromModel(expression);
Enum defaultSelectValue = helper.ViewData.Eval(name) as Enum;
IList<SelectListItem> selectList = EnumHelper.GetSelectList(typeof(TProperty), defaultSelectValue);
List<KeyValuePair<string, string>> optionData = new List<KeyValuePair<string, string>>();
foreach (var item in selectList)
{
optionData.Add(new KeyValuePair<string, string>(item.Text, item.Value));
}
return BuildRadioButtonList(helper, expression, name, Convert.ToInt32(defaultSelectValue).ToString(), optionData, htmlAttributes, appendOptionLabel, optionLabel, direction);
}
如何使用方法
透過包裝後的方法,在使用上只要傳入資料集或列舉值就可回傳RadioButtoList可使用
<div class="form-group">
@Html.LabelFor(model => model.ProductId, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.RadioButtonListForList(DataUtility.GetDatas(), "ProductId", "ProductName", model => model.ProductId, direction: RepeatDirections.Vertical)
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Direction, htmlAttributes: new { @class = "control-label col-md-2" })
<div class="col-md-10">
@Html.RadioButtonListForEnum(model=>model.Direction)
</div>
</div>
完整範例
https://github.com/kimx/RadioButtonListLab/