Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I make Html.CheckBoxFor() work on a string field?

I'm using ASP.NET MVC3 with Razor and C#. I am making a form builder of sorts, so I have a model that has a collection of the following object:

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

MyFormType is just an enum that tells me if the form field is a checkbox, or textbox, or file upload, or whatever. My editor template looks something like this (see the comment):

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

I tried casting/converting the m.Value to a bool in the lambda expression for CheckBoxFor(), but that threw an error. I would just manually construct a checkbox input, but CheckBoxFor() seems to do two things that I can't seem to replicate:

  1. Creates a hidden input that somehow gets populated by the checkbox. This appears to be what the model binder picks up.
  2. Generates the name form the object so that the model binder gets the value into the right property.

Does anyone know a way around using CheckBoxFor() on a string, or a way to replicate its functionality manually, so that I can make this work?

like image 517
jrizzo Avatar asked Aug 25 '11 19:08

jrizzo


People also ask

How do you create a check box in Cshtml?

Checkboxes are rendered in HTML by setting the type attribute in an input element to checkbox : <input type="checkbox">

How check checkbox is checked or not in ASP NET MVC?

This blog defines how to get checked property of Checkbox in MVC. Create a View with Checkbox. aspx Page. Run and click on button after selectin checkbox and see results.


2 Answers

One way is to create your own htmlhelper extension method.

    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));
    }

The usage is the same as CheckBoxFor helper (e.Value is a string)

@Html.CheckBoxStringFor(e => e.Value)
like image 110
mdm20 Avatar answered Sep 28 '22 03:09

mdm20


You could also add a property on your 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; }
    }

Your view would be something like this:

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

Use Boolean.TryParse if you want to avoid exceptions.

like image 32
Robin van der Knaap Avatar answered Sep 28 '22 01:09

Robin van der Knaap