自定义CheckBoxListFor Html助手。如何绑定到viewmodel属性?

时间:2017-01-26 20:46:23

标签: c# asp.net-mvc html-helper model-binding checkboxlist

我正在创建一个自定义的Html帮助程序来处理复选框列表。我知道网上有很多关于这个主题的信息,但是我没有看到太多尝试按照我下面的方式生成HTML。

所需的呈现HTML

"SF,HR"

我使用不同的复选框而不仅仅是布尔值,因为我想利用这样一个事实,即在表单帖子中,我会得到一个以逗号分隔的选中的列表价值观。例如,如果选择了Sci-Fi和Horror,我会得到public class MovieViewModel { public string Name { get;set; } public string Year { get;set; } public IEnumerable<string> Genres { get;set; } public IEnumerable<SelectListItem> GenreOptions { get;set; } }

查看模型

@Html.EditorFor(model => model.Name)
@Html.EditorFor(model => model.Year)
@Html.CheckBoxListFor(model => model.Genres, Model.GenreOptions)

视图

在我看来,我基本上是这样做的:

    public static MvcHtmlString CheckboxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        IEnumerable<SelectListItem> items)
    {
        if (items == null) return null;

        var itemsList = items.ToList();
        if (!itemsList.Any()) return null;

       // How do I get "Genres" name from the passed expression from viewmodel, without passing the hardcoded string "genres"?
        var checkboxGroupName = expression.what????

        var sb = new StringBuilder();
        sb.Append("<ul>");

        foreach (var item in itemsList)
        {
            var checkbox = $"<input type=\"checkbox\" name=\"{checkboxGroupName}\" value=\"{item.Value}\" />";
            sb.Append($"<li class=\"checkbox\"><label>{checkbox} {HttpUtility.HtmlEncode(item.Text)}</label></li>");
        }

        sb.Append("</ul>");

        return MvcHtmlString.Create(sb.ToString());
    }

自定义Html助手

所以,我开始创建一个自定义的Html助手,但我对这些没有太多的经验,这就是我需要帮助的地方:

name

正如您在上面的评论中所看到的,我不知道如何动态地将viewmodel属性名称“Genres”分配给复选框“model => model.Genres”,而不对其进行硬编码。如何从{{1}}表达式中获取它?

2 个答案:

答案 0 :(得分:2)

要获取属性名称,请使用

var name = ExpressionHelper.GetExpressionText(expression);

将提供完全限定的名称,例如@CheckboxListFor(m => m.Movies.Genres, ....)将返回Movies.Genres

但是考虑到你为你的模型使用自定义EditorTemplate(这是父模型的属性)的情况,那么你还需要获得`HtmlFieldPrefix,如果它存在,则在它前面添加名称

您当前的代码没有为您提供正确的绑定,例如,如果Genres包含与Value的{​​{1}}属性匹配的值,则应在呈现视图时检查相关的复选框。你的代码应该是

SelectListItem

答案 1 :(得分:1)

您可以使用ModelMetaData类通过以下代码行从Expression<Func<TModel,TProperty>>类型的参数中获取Html Helper中传递的属性的名称:

var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
var checkboxGroupName = metadata.PropertyName;

这是一篇解释How to Create Custom Strongly Typed Html Helpers的文章,可能对您有所帮助。