12

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

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

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

~/Views/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!
    }
}

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

  1. 创建一个隐藏的输入,该输入以某种方式被复选框填充。这似乎是模型活页夹拾取的内容。
  2. 从对象生成名称,以便模型绑定器将值获取到正确的属性中。

有谁知道在字符串上使用 CheckBoxFor() 的方法,或者手动复制其功能的方法,以便我可以完成这项工作?

4

4 回答 4

13

一种方法是创建自己的 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 助手相同(e.Value 为字符串)

@Html.CheckBoxStringFor(e => e.Value)
于 2011-08-25T20:07:51.683 回答
12

您还可以在视图模型上添加一个属性:

    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。

于 2011-08-25T20:41:56.097 回答
4

使用复选框,这种简单的方法效果很好

@Html.CheckBox("IsActive", Model.MyString == "Y" ? true : false)
于 2015-01-20T20:06:52.227 回答
0

我也有这个问题,但无法修改视图模型。尝试了 mdm20s 解决方案,但我怀疑它不适用于集合属性(它不会像原生 html 帮助程序那样将索引添加到名称和 id)。要克服这个问题,您可以改用 Html.CheckBox。它添加了正确的索引,您可以自己传递复选框的值。

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

于 2012-08-16T01:16:36.407 回答