Как я могу заставить Html.CheckBoxFor() работать в поле строки?

Я использую ASP.NET MVC3 с Razor и С#. Я создаю компоновщик форм, поэтому у меня есть модель, у которой есть коллекция следующего объекта:

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!
    }
}

Я попробовал кастинг/преобразование m.Value в bool в выражении лямбда для CheckBoxFor(), но это заставило ошибку. Я просто вручную создаю флажок, но CheckBoxFor(), похоже, выполняет две вещи, которые, как я могу, не реплицируются:

  • Создает скрытый ввод, который каким-то образом заполняется флажком. Похоже, это то, что подбирает модельное связующее.
  • Генерирует имя формы для объекта, чтобы привязка к модели вносила значение в правильное свойство.

Кто-нибудь знает способ использования CheckBoxFor() в строке или способ репликации ее функций вручную, чтобы я мог сделать эту работу?

Ответ 1

Вы также можете добавить свойство на свою модель просмотра:

    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, если вы хотите избежать исключений.

Ответ 2

Один из способов - создать собственный метод расширения 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)

Ответ 3

Используйте флажок, этот простой способ отлично работает

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

Ответ 4

У меня тоже была эта проблема, но мне не удалось изменить модель представления. Пробовал решение mdm20s, но, как я подозревал, он не работает над свойствами коллекции (он не добавляет индексы к именам и идентификаторам, например, встроенным html-помощникам). Чтобы преодолеть это, вы можете вместо этого использовать Html.CheckBox. Он добавляет правильные индексы, и вы можете передать значение флажка самостоятельно.

Если вы действительно хотите использовать выражение, вы всегда можете написать оболочку, похожую на mdm20s, но заменить все после TryParse return Html.CheckBox("propertyName", isChecked). Очевидно, вам также нужно добавить using System.Web.Mvc.Html.