Morning all.
I can see this has been discussed elsewhere but was wondering if anything had change or things made simpler in MVC 4 for simpletons like me?!
Scenario
I have the following,edited, model:
public class CorporateDetails
{
public Guid? Id { get; set; }
[Key]
public int CorporateDetailId { get; set; }
public int? EmsId { get; set; }
public string EmsName { get; set; }
public virtual EmsType EmsType { get; set; }
}
public class EmsType
{
[Key]
public int? EmsId { get; set; }
public string EmsName { get; set; }
public virtual ICollection<EmsType> EmsTypes { get; set; }
}
With the following standard create view:
<fieldset>
<legend>CorporateDetails</legend>
<div class="editor-label">
@Html.LabelFor(model => model.EmsId, "EmsType")
</div>
<div class="editor-field">
@Html.DropDownList("EmsId", String.Empty)
@Html.ValidationMessageFor(model => model.EmsId)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.EmsName)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.EmsName)
@Html.ValidationMessageFor(model => model.EmsName)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
This gives me, out of the box, a beautiful drop down list a la Scott Gu's blog
Now my real question is this - how can I effectively convert this drop down box to what will effectively be a multi select,checkbox list?
Again, apologies for going over trodden ground but I was just testing the water to see if any updates have occurred.
Please note, first MVC project so go gently, I'm feeling very thick again :'(
So in this article, I explain how to create a checkboxlist in MVC. Click "File" -> "New" -> "Project...". Select "ASP.Net MVC4 WebApplication", provide your Project Name, for example I used "CheckboxListDemo", then click "Ok". Now select "Internet Application", and then click "Ok".
Razor offers two ways to generate checkboxes. The recommended approach is to use the input tag helper. Any boolean property of the PageModel will render a checkbox if it is passed to the asp-for attribute, so long as the property is not nullable: public class IndexModel : PageModel.
Right ok, I have got it sorted - hurrah! As you can see from the comments, there were a few issues that came up but please find below the complete solution which DOES work :D
Model
public class CorporateDetails
{
public Guid? Id { get; set; }
[Key]
public int CorporateDetailId { get; set; }
public int[] EmsId { get; set; }
}
public class EmsType
{
[Key]
public int EmsId { get; set; }
public string EmsName { get; set; }
public virtual ICollection<EmsType> EmsTypes { get; set; }
}
Controller
public ActionResult Create()
{
CorporateDetails corporatedetails = new CorporateDetails();
ViewBag.EmsId = new MultiSelectList(db.EmsTypes, "EmsId", "EmsName");
return View(corporatedetails);
}
Extension (placed in a folder in the root of the project)
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty[]>> expression, MultiSelectList multiSelectList, object htmlAttributes = null)
{
//Derive property name for checkbox name
MemberExpression body = expression.Body as MemberExpression;
string propertyName = body.Member.Name;
//Get currently select values from the ViewData model
TProperty[] list = expression.Compile().Invoke(htmlHelper.ViewData.Model);
//Convert selected value list to a List<string> for easy manipulation
List<string> selectedValues = new List<string>();
if (list != null)
{
selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); });
}
//Create div
TagBuilder divTag = new TagBuilder("div");
divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);
//Add checkboxes
foreach (SelectListItem item in multiSelectList)
{
divTag.InnerHtml += String.Format("<div><input type=\"checkbox\" name=\"{0}\" id=\"{0}_{1}\" " +
"value=\"{1}\" {2} /><label for=\"{0}_{1}\">{3}</label></div>",
propertyName,
item.Value,
selectedValues.Contains(item.Value) ? "checked=\"checked\"" : "",
item.Text);
}
return MvcHtmlString.Create(divTag.ToString());
}
Extension registered in web config of the Views
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization"/>
<add namespace="System.Web.Routing" />
<add namespace="MyProject.Extensions" />
</namespaces>
</pages>
View
@model Valpak.Websites.HealthChecker.Models.CorporateDetails
@{
ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>CorporateDetails</legend>
<div class="editor-label">
@Html.CheckBoxListFor(model => model.EmsId, (MultiSelectList) ViewBag.EmsId)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
<div>
@Html.ActionLink("Back to List", "Index")
</div>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Which gives me a lovely list of check boxes. Hurrah!
Thanks Darin for your help, I've marked this as the answer but +50 for your time and effort.
Nice solution -
Just for others reference - I, like you, had run into a need for a checkboxlist - I have been using this here:
http://www.codeproject.com/Articles/292050/CheckBoxList-For-a-missing-MVC-extension
It works great... very well written - hope this can help someone.
Loren
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With