我正在尝试创建(或者更好地找到)一个自定义html扩展方法,该方法与ListBoxFor类似的工作方式有效,但是呈现一组复选框而不是选择多个。
解决这个问题的最佳方式是什么?我很好奇ListBoxFor方法是如何工作的,当它只传递一个表达式和一个可枚举的SelectListItems时,它只选择了默认项。它没有通过模型,所以它如何知道何时选择正确的项目(不知何故它似乎能够做到这一点)?另外,它如何根据匿名对象编写html属性?
答案 0 :(得分:2)
您尚未提供任何有关您要实现的目标的详细信息和具体示例。到目前为止,您还没有提供任何源代码,以解决您遇到的问题。下次在StackOverflow上提出问题时,请这样做,以使您的问题更有意义,并专注于特定问题。
无论如何,这是一个例子。假设您已定义了一个视图模型:
public class MyViewModel
{
public IEnumerable<string> SelectedValues { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
}
和一个控制器,它将使用值填充此视图模型,并希望在POST操作中获取视图中的选定值:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new MyViewModel
{
SelectedValues = new[] { "1", "3" },
Values = new[]
{
new SelectListItem { Value = "1", Text = "item 1" },
new SelectListItem { Value = "2", Text = "item 2" },
new SelectListItem { Value = "3", Text = "item 3" },
}
};
return View(model);
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
// model.SelectedValues will contain the ids of items that were checked
// in the checkbox list
}
}
然后是一个视图:
@model MyViewModel
@using (Html.BeginForm())
{
@Html.CheckBoxListFor(x => x.SelectedValues, Model.Values, null)
<button type="submit">OK</button>
}
好的,到目前为止一切顺利。最后一部分是尝试实现这个CheckBoxListFor
帮助器。显然,根据您的具体要求和背景,可能有很多可能的方法(请参阅答案开头的评论)。所以这里只是一些可以帮助您入门的示例实现:
public static class HtmlExtnsions
{
public static IHtmlString CheckBoxListFor<TModel, TProperty>(
this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,
IEnumerable<SelectListItem> selectList,
object htmlAttributes
)
{
var name = ExpressionHelper.GetExpressionText(expression);
string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
var values = GetModelStateValue(htmlHelper.ViewData, fullHtmlFieldName, typeof(string[]));
if (values == null)
{
values = htmlHelper.ViewData.Eval(fullHtmlFieldName);
}
if (values != null)
{
var collection =
from object value in values as IEnumerable
select Convert.ToString(value, CultureInfo.CurrentCulture);
var hashSet = new HashSet<string>(collection, StringComparer.OrdinalIgnoreCase);
var list = new List<SelectListItem>();
foreach (var item in selectList)
{
item.Selected = ((item.Value != null) ? hashSet.Contains(item.Value) : hashSet.Contains(item.Text));
list.Add(item);
}
selectList = list;
}
var sb = new StringBuilder();
foreach (var item in selectList)
{
var checkbox = new TagBuilder("input");
checkbox.Attributes["type"] = "checkbox";
checkbox.Attributes["name"] = fullHtmlFieldName;
checkbox.Attributes["value"] = item.Value;
checkbox.GenerateId(fullHtmlFieldName);
if (item.Selected)
{
checkbox.Attributes["checked"] = "checked";
}
sb.Append(checkbox.ToString(TagRenderMode.SelfClosing));
sb.Append(item.Value);
}
return new HtmlString(sb.ToString());
}
private static object GetModelStateValue(ViewDataDictionary viewData, string key, Type destinationType)
{
ModelState modelState;
if (viewData.ModelState.TryGetValue(key, out modelState) && modelState.Value != null)
{
return modelState.Value.ConvertTo(destinationType, null);
}
return null;
}
}