如何让Html.CheckBoxFor()在字符串字段上工作?

时间:2011-08-25 19:06:45

标签: c# asp.net-mvc asp.net-mvc-3 razor mvc-editor-templates

我正在使用带有Razor和C#的ASP.NET MVC3。我正在制作各种表单构建器,因此我有一个具有以下对象集合的模型:

public class MyFormField
{
    public string Name { get; set; }
    public string Value { get; set; }
    public MyFormType Type { get; set; }
}

MyFormType只是一个枚举,告诉我表单字段是复选框,文本框还是文件上传,或者其他什么。我的编辑器模板看起来像这样(参见评论):

〜/查看/ EditorTemplates / MyFormField.cshtml

@model MyFormField
@{
    switch (Model.Type)
    {
        case MyFormType.Textbox:
            @Html.TextBoxFor(m => m.Value)
        case MyFormType.Checkbox:
            @Html.CheckBoxFor(m => m.Value)  // This does not work!
    }
}

我尝试将m.Value转换/转换为CheckBoxFor()的lambda表达式中的bool,但是这引发了错误。我只是手动构造一个复选框输入,但CheckBoxFor()似乎做了两件我似乎无法复制的事情:

  1. 创建一个隐藏的输入,以某种方式由复选框填充。这似乎是模型绑定器的选择。
  2. 从对象生成名称,以便模型绑定器将值输入到正确的属性中。
  3. 有没有人知道在字符串上使用CheckBoxFor()的方法,或者手动复制其功能的方法,以便我可以使这个工作?

4 个答案:

答案 0 :(得分:12)

您还可以在viewmodel上添加一个属性:

    public class MyFormField
    {
        public string Name { get; set; }
        public string Value { get; set; }

        public bool CheckBoxValue
        {
            get { return Boolean.Parse(Value); }
        }

        public MyFormType Type { get; set; }
    }

你的观点是这样的:

@model MyFormField
@{
    switch (Model.Type)
    {
        case MyFormType.Textbox:
            @Html.TextBoxFor(m => m.Value)
        case MyFormType.Checkbox:
            @Html.CheckBoxFor(m => m.CheckBoxValue)  // This does work!
    }
}

如果要避免异常,请使用Boolean.TryParse。

答案 1 :(得分:11)

一种方法是创建自己的htmlhelper扩展方法。

    public static MvcHtmlString CheckBoxStringFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, string>> expression)
    {
        // get the name of the property
        string[] propertyNameParts = expression.Body.ToString().Split('.');
        string propertyName = propertyNameParts.Last();

        // get the value of the property
        Func<TModel, string> compiled = expression.Compile();
        string booleanStr = compiled(html.ViewData.Model);

        // convert it to a boolean
        bool isChecked = false;
        Boolean.TryParse(booleanStr, out isChecked);

        TagBuilder checkbox = new TagBuilder("input");
        checkbox.MergeAttribute("id", propertyName);
        checkbox.MergeAttribute("name", propertyName);
        checkbox.MergeAttribute("type", "checkbox");
        checkbox.MergeAttribute("value", "true");
        if (isChecked)
            checkbox.MergeAttribute("checked", "checked");

        TagBuilder hidden = new TagBuilder("input");
        hidden.MergeAttribute("name", propertyName);
        hidden.MergeAttribute("type", "hidden");
        hidden.MergeAttribute("value", "false");

        return MvcHtmlString.Create(checkbox.ToString(TagRenderMode.SelfClosing) + hidden.ToString(TagRenderMode.SelfClosing));
    }

用法与CheckBoxFor helper相同(e.Value是一个字符串)

@Html.CheckBoxStringFor(e => e.Value)

答案 2 :(得分:4)

使用Checkbox,这种简单方法可以正常使用

@Html.CheckBox("IsActive", Model.MyString == "Y" ? true : false)

答案 3 :(得分:0)

我也有这个问题,但无法修改视图模型。试过mdm20s解决方案,但我怀疑它不适用于集合属性(它不会将索引添加到名称和id,如本机html助手)。要解决此问题,您可以使用Html.CheckBox。它添加了正确的索引,您可以自己传递复选框的值。

如果你真的想使用一个表达式,你总是可以编写一个类似于mdm20s的包装器,但是在TryParse之后替换所有内容。 return Html.CheckBox("propertyName", isChecked)。显然,您还需要添加using System.Web.Mvc.Html