Wednesday, 20 July 2011

ASP.Net MVC3 checkboxlist htmlhelper extension

 

Download source code : https://github.com/Azadehkhojandi/CheckboxListFor
Related Posts




When you have a list of Enum in your Viewmodel and want to show it as a check boxes in your view with razor in mvc3 what do you do?

 
1-view model



public enum Mytype
    {
        type1,
        type2,
        type3,
        type4
    }
public class testViewModel
    {
        //Some other properties
        public IList<Mytype> Selectedtypes {get;set;}
    }

 
2-controller
 
       public ActionResult test(string page)
        {
            var model = new testViewModel() { Selectedtypes =new List<Mytype>() {} };
            TempData["page"] = page;
            return View(page, model);
        }
       [HttpPost ]
        public ActionResult test(FormCollection form, testViewModel model)
        {
           //do something
           //show page with gathered data for test          
           string page=TempData["page"].ToString();
           TempData["page"] = page;
           ViewBag.Message = "Gathered data:";
           return View(page, model);
        }

3-view



 way 1 



@using (Html.BeginForm("test","home"))
{
       
  foreach (Mytype item in Enum.GetValues(typeof(Mytype)))
    {
        <p>
        @Html.Label("Selectedtypes"+item ,Enum.GetName (typeof(MvcHandy.Models.Mytype),item)) 
        @{bool t=Model.Selectedtypes.Any(x => x == item);}
        <input name="Selectedtypes" id="Selectedtypes" type="checkbox"  @(t ? "checked='checked'" : "")  value="@item"/>          
        </p>
    }
  
    <input type="submit" name="submit" value="submit" />
}



way 2

adding a helper class

public static class Helper
    {
        public static MvcHtmlString CheckBoxList<enumType>(this HtmlHelper htmlHelper,object model)
        {
            PropertyInfo propertyInfo = model.GetType().GetProperties().Where(x => x.PropertyType == typeof(IList<enumType>)).FirstOrDefault();
            TagBuilder  tg=new TagBuilder("div");
            string innerhtml="";
            foreach (var item in Enum.GetValues(typeof(enumType)))
            {             
                IList<enumType> v = propertyInfo.GetValue(model, null) as IList<enumType>;
                bool ischecked = v.Any(x => x.ToString() == item.ToString());            
                innerhtml = innerhtml +"<P>"+ htmlHelper.Label(propertyInfo.Name + item, Enum.GetName(typeof(enumType), item)).ToString() +
                    @"<input name='" + propertyInfo.Name + "' id='" + propertyInfo.Name + "' type='checkbox' " +((ischecked)? "checked='checked'" :"")+ "  value=" + item + ">"+"</p>";
             
            }
            tg.SetInnerText(innerhtml);
            return new MvcHtmlString(innerhtml);
        }
}

and it's obvious that view is much smaller and more readable
@using (Html.BeginForm("test","home"))
{
    <div>
        @(Html.Raw( Html.CheckBoxList<MvcHandy.Models.Mytype>(Model).ToString()))
    </div>
   
     <input type="submit" name="submit" value="submit" />
}


way 3



public static class Helper
    {
public static MvcHtmlString CheckBoxListFor<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper,Expression<Func<TModel,IEnumerable< TEnum>>> expression)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
            TagBuilder tg = new TagBuilder("div");
            string innerhtml = "";
            var model = metadata.Model as IEnumerable<TEnum>;
            foreach (var item in Enum.GetValues(typeof(TEnum)))
            {
              
                bool ischecked =(model==null) ?false : model.Any(x => x.ToString() == item.ToString());
               
                innerhtml = innerhtml +"<p>"+ htmlHelper.Label(metadata.PropertyName + item, Enum.GetName(typeof(TEnum), item)).ToString() +
                    @"<input name='" + metadata.PropertyName + "' id='" + metadata.PropertyName + "' type='checkbox' " + ((ischecked) ? "checked='checked'" : "") + "  value=" + item + ">"+"</p>";

            }
            tg.SetInnerText(innerhtml);
            return new MvcHtmlString(innerhtml);
            
        }
    }


@using (Html.BeginForm("test", "home"))
{     
    <div>
        @Html.CheckBoxListFor(x => x.Selectedtypes)
    </div>
    <input type="submit" name="submit" value="submit" />
}


Post a Comment