Click here to Skip to main content
Click here to Skip to main content

CheckBoxList(For) - A missing MVC extension

By , 6 May 2013
 

Check out official website with live examples and documentation:

mvccbl.com

Latest Version (for .NET 4.0 or 4.5 and MVC4)

Install via NuGet Package Manager Console:

Install-Package MvcCheckBoxList   

This version has few breaking changes, so if something doesn't work after update, check documentation.

Download binary (MvcCheckBoxList.dll)
Download sample MVC project with extension's stable source code

Contents

Introduction

One of the cool features of Microsoft MVC web development framework since its inception, was its rich Html helpers library. It provided helpers to create most common html controls like text boxes, drop down lists, text areas, etc. It is done by simply typing Html.<smth> on the MVC view page.

Its all been good and easily customizable, until developers been eventually reaching one blank spot... That spot was a creation of a checkbox lists. There was none, and there is no any control to handle that functionality as of now.

To create a checkbox list a developer would have to use a combination of FOR or FOREACH cycle and some html <input> along with it.

While not being a hard thing to do, it could possibly become pretty time consuming. Especially when project was getting bigger and fatter with a whole bunch of repetitive code lying around. And think about adding some advanced functionality and layout. For example, when we want to disable some checkboxes, while at the same time being able to POST it back to your controller, and on top of that, putting it into the <table>, it would become quite bigger than before.

But what if we would want to put it into several columns? It would require even more customization. And would get even bigger. This little extension intends to simplify this task while making it more inline with general MVC workflow.

This plugin is just an extension of MVC class 'HtmlHelper', which is used for all Html helpers on MVC views. Since there is no supported CheckBoxList extension built into MVC, this plugin adds it.  

Using the code 

All examples below are shown using MVC + Razor view engine. Examples will demonstrate recommended real-world scenario of using this extension.

Given we have...

Base class City:

public class City {
  public int Id { get; set; }           // Integer value of a checkbox
  public string Name { get; set; }      // String name of a checkbox
  public object Tags { get; set; }      // Object of html tags to be applied to checkbox, e.g.: 'new { tagName = "tagValue" }'
  public bool IsSelected { get; set; }  // Boolean value to select a checkbox on the list
}   
And we use CitiesViewModel view model on our view:
public class CitiesViewModel {
  public IList<City> AvailableCities { get; set; }
  public IList<City> SelectedCities { get; set; }
  public PostedCities PostedCities { get; set; }
}

// Helper class to make posting back selected values easier
public class PostedCities {
  public string[] CityIDs { get; set; }
} 
And our controller accepts class PostedCities:
public ActionResult Examples(PostedCities postedCities) {
  return View(/* Create View Model */);
}           

Source: documentation > Given we have...
Base Overloads
Now we can create a control on the view, first - keep in mind base checkbox list call structure:
@Html.CheckBoxList("LIST_NAME", 
                   model => model.LIST_DATA, 
                   entity => entity.VALUE, 
                   entity => entity.NAME, 
                   model => model.SELECTED_VALUES) // or entity => entity.IS_CHECKED
Or with strongly-typed name:
@Html.CheckBoxListFor(model => model.LIST_NAME, 
                      model => model.LIST_DATA, 
                      entity => entity.VALUE, 
                      entity => entity.NAME, 
                      model => model.SELECTED_VALUES) // or entity => entity.IS_CHECKED 
So in our example it'll look like this:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs, 
                      model => model.AvailableCities, 
                      entity => entity.Id, 
                      entity => entity.Name, 
                      model => model.SelectedCities) 

Or if using boolean selector: 

@Html.CheckBoxListFor(model => model.PostedCities.CityIDs, 
                      model => model.AvailableCities, 
                      entity => entity.Id, 
                      entity => entity.Name, 
                      entity => entity.IsSelected)  

where entity.IsSelected is a boolean value from database, 

And another way to use boolean selector: 

@Html.CheckBoxListFor(model => model.PostedCities.CityIDs, 
                      model => model.AvailableCities, 
                      entity => entity.Id, 
                      entity => entity.Name, 
                      entity => selectedIds.Contains(x.Id)) 

where selectedIds.Contains(x.Id) returns bool if item Id matches the list.  

Source: documentation > Base Overloads.

Basic Settings:
Since five base properties (see previous section) don't change, only extra ones will be shown, so placeholder ... means usage of five base properties. You might need to add this reference to your view first (namespace for Position enum and others):
@using MvcCheckBoxList.Model 
1. Set position (direction) of the list:
@Html.CheckBoxListFor( ... , Position.Horizontal) 
Position Can be Position.Horizontal, Position.Vertical, Position.Horizontal_RightToLeft, or Position.Vertical_RightToLeft where last two are to reverse checkbox and label for right-to-left languages 2. Set html attributes for both checkbox and label:
@Html.CheckBoxListFor( ... , x => new { @class="class_name" }) // Tags will be applied to all checkbox/label combos  
Or get Tags object from database:
@Html.CheckBoxListFor( ... , x => x.Tags) // x.Tags will be applied only to particular checkbox/label combo 
3. Set html attributes and position:
@Html.CheckBoxListFor( ... , Position.Horizontal, x => new { @class="class_name" }) 
4. Set html attributes for all, disabled values, position, and individual html attributes (all attributes will be merged together):
@Html.CheckBoxListFor( ... , x => new { @class="class_name" }, new[] {"3", "5", "7"}, Position.Horizontal, x => x.Tags) 
Source: documentation > Basic Settings.
Advanced Settings:

You might need to add this reference to your view first (namespace for HtmlListInfo class and others): 

@using MvcCheckBoxList.Model 

1. Set custom layout using HtmlListInfo class: 

var htmlListInfo = new HtmlListInfo(HtmlTag.table, 2, new { @class="class_name" }, TextLayout.Default, TemplateIsUsed.Yes);

@Html.CheckBoxListFor( ... , htmlListInfo)  

There, in HtmlListInfo class, HtmlTag can be HtmlTag.table or HtmlTag.vertical_columns; 2 is a number of columns; TextLayout can be TextLayout.Default or TextLayout.RightToLeft (for right to left languages) 

2. Set layout with HtmlListInfo class and set html attributes: 

@Html.CheckBoxListFor( ... , htmlListInfo, x => new { tagName = "tagValue" })  // Tags will be applied to all checkbox/label combos 

Or get Tags object from database: 

@Html.CheckBoxListFor( ... , htmlListInfo, x => x.Tags })  // x.Tags will be applied only to particular checkbox/label combo  

3. Set html attributes for all, set layout with HtmlListInfo, set disabled values, and individual html attributes (all attributes will be merged together): 

@Html.CheckBoxListFor( ... , new { @class="class_name" }, htmlListInfo, new[] {"3", "5", "7"}, x => x.Tags)  

There, x.Tags is a value of type object and should be equal to something similar to this new { tag1 = "value1", tag2="value2" } and represent one or more custom html attributes, and will be applied to both checkbox and label. 

Also note that x.Tags is an optional parameter for each available overload. Just add it as a last parameter to @Html.CheckBoxListFor( ... , x => x.Tags) checkbox list call.  

Source: documentation > Advanced Settings

Live Examples 

Official website (from source code) has a dedicated live examples section to demonstrate how this extension will work in various real-world scenarios.  

Please see this extension in action here:  mvccbl.com > Examples

History 

  • v.1.4.4.4
    • Adds support for both .NET 4.0 and 4.5
  • v.1.4.3.0
    • Added support for right-to-left languages (by flipping the order of checkbox and label)
    • Removed model-independent functionality
  • v.1.4.2.3
    • Fixed a bug where it requires MVC4 dependency (System.Web.WebPages 2.0.0.0), and doesn't work in MVC3 projects...
  • v.1.4.2.2
    • NuGet package added!
    • Additional parameter for both 'CheckBoxList' and 'CheckBoxListFor' - 'htmlAttributesExpr' allows to pass custom html tags from database to be applied to each individual checkbox (see good exaple of this in sample MVC3 project)
    • Improved name generation
    • Numerous other small fixes...
  • v.1.3c
    • Some minor bug fixes done
    • Created a sample MVC3 .NET 4.0 site which comes along with this control, so you can test it first hand!
  • v.1.3b
    • Added function annotations, some code cleanup
  • v.1.3a
    • Instead of plain checkbox name it now creates a label linked to checkbox, so you can also click on the label to select that checkbox! Many thanks to william0565 for idea !
  • v.1.3
    • 'CheckBoxListFor' now generates full name from a lambda expression: e.g.: @Html.CheckBoxListFor(model => model.SomeClass.SubClass .... ) will create a list of checkboxes with 'name="SomeClass.SubClass"', where older version would create only 'name="SubClass"'
  • v.1.2
    • You can now create strongly typed checkbox list from your view model!
    • Added new method 'CheckBoxListFor' to be used with strongly typed approach
  • v.1.1
    • Added new option 'HtmlTag.vertical_columns', which allows checkboxes to be arranged inside 4 vertically sorted floating sections
    • Overload functions cleanup
    • Overall code cleanup
  • v.1.0
    • Initial release!

Contributors

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Mikhail Tsennykh
Web Developer Nûby, Inc.
United States United States
Member
Namaste from Monroe, Louisiana!

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
SuggestionCustomCheckBoxmemberRaul Iloc6 May '13 - 19:25 
I have implemented in a easy way the "Custom Check Box" by using custom HTML helpers in my next article: MVC Basic Site: Step 3 – Dynamic Layouts and Site Admin with: AJAX, jqGrid, Controller Extensions, HTML Helpers, and more[^]
 
I managed also the cases when the check boxes should be read only.
Raul Iloc

GeneralMy vote of 5memberDmitry A. Efimenko6 May '13 - 11:30 
Great article, Mikhail! You might remember me mentioning that I'll be creating a library of html helpers for TwitterBootstrap. It is available now here. I also gave you credit there!
GeneralRe: My vote of 5memberMikhail Tsennykh6 May '13 - 11:59 
That's awesome! I definitely remember about your project, Dmitry, so I'll check out your article soon, thanks for rating!!! Smile | :)
QuestionWhat?memberDeviant Sapphire6 May '13 - 9:59 
Hello,
 
Nice post,
 
I have a question though. Where are the pictures of the results. These are needed to attract more viewers. Smile | :)
 
- Deviant
AnswerRe: What?memberMikhail Tsennykh6 May '13 - 12:03 
Yes! That is a great idea indeed. I figured live examples on the official site should be enough, but I agree some screenshots would never hurt! Smile | :)
QuestionUsing extension with List<string> not with List<SomeComplexClass>memberKamilBedkowski29 Apr '13 - 1:26 
Extension looks (and works) great,but have one question:
Now i want to choose items,whose type is not complex class like your "City" from example,but for simple string.
In that case i don't have any Id/Value pair in element,each element of that list is one simple string.
 
Can your extension handle with something like that (in any example i saw pair key/value is required).
 
Thanks in advance for any answer.
 
Regards,
 
Kamil
AnswerRe: Using extension with List<string> not with List<SomeComplexClass>memberMikhail Tsennykh30 Apr '13 - 5:16 
Hi Kamil,
 
To do what you want you can simply ajust the 'complex' class to have only one string property and use that for both value and text of the list, e.g.:
public class YourClass {
  public string Name { get; set; }
}
Then call it like that:
@Html.CheckBoxList("YourClass",                
                   model => model.ListOfYourClass,           
                   property => property.Name,               
                   property  => property.Name,             
                   model => null)    
I hope that'll work for you!
QuestionLabel not with checkboxmemberMember 992203618 Mar '13 - 14:18 
Has anyone seen the checkbox split from the label? For me the checkbox appears with the label underneath. I am doing any special formatting. When I view source and copy n paste the code nto a plain html file it looks fine but on my site it's split?Confused | :confused: anyone?
AnswerRe: Label not with checkboxmemberPhilippe Mori6 May '13 - 12:33 
You can uses developer tools in Internet Explorer to identify what style are applied on every item. And you can even uncheck a checkbox so that that style won't be applied and immediatly see the resulting page.
 
It all depends on the content of the CSS style sheet.
Philippe Mori

AnswerRe: Label not with checkboxmemberMikhail Tsennykh7 May '13 - 4:05 
That can only happen if the something is limiting the width of area where your checkboxes are generated. Check html source and make sure there is enough space for both label's text and checkbox.
QuestionConflict w/ the "Position" enummemberEldar18 Mar '13 - 9:57 
Great addition! Unfortunately, a class named "Position" is a first-class citizen in my project and it conflicts w/ your "Position" enum. Why is your "Position" enum in the global namespace?
AnswerRe: Conflict w/ the "Position" enummemberMikhail Tsennykh18 Mar '13 - 11:33 
No particular reason, Eldar, it was just convenient at the moment when it was coded - no need to define @using statement on the views. I am confident though, that it was not too forward-looking decision)) It should indeed have it's own namespace.
 
Anyway, I moved all enums/classes to their own namespace MvcCheckBoxList.Model, grab that new dll here (for .NET 4.5 only):
https://dl.dropbox.com/u/37444966/CodeProject/MvcCheckBoxList.v.1.4.4.4.dll[^]
(if you use .net 4.0, let me know)
 
So now you'd need also define this on your view:
@using MvcCheckBoxList.Model
I also pushed that change to the dev branch on Github.
QuestionModelState.IsValid is always false after post with checkboxlist datamemberMember 82744462 Mar '13 - 10:13 
Hi,
I have a little problem with posting data to the controller.
I have class RoleViewModel and GroupAddViewModel that has property which is list of RoleViewModel objects.
Binding to CheckBoxList works fine, but if I post model with data back to the controller I have ModelState.IsValid always set to false because of conversion from string to RoleViewModel problem. So it looks like CheckBoxListFor tries to pass array of strings in model object instead of collection of RoleViewModel objects.
 
Do you have any solution (except use of ModelState.Clear()) to work-around this issue? Or am I doing sth. wrong? Smile | :)
 
Here is my code:
1. View model:
    public class GroupAddFacadeViewModel
    {
        public GroupAddViewModel Group { get; set; }
 
        public IEnumerable<RoleViewModel> Roles { get; set; }
    }
2. RoleViewModel:
    public class RoleViewModel
    {
        public int RoleID { get; set; }
 
        public string Name { get; set; }
    }
3. GroupViewModel:
    public class GroupAddViewModel
    {
        [DisplayName("Name")]
        public string Name { get; set; }
 
        [DisplayName("Description")]
        public string Description { get; set; }
 
        [DisplayName("Roles")]
        public IEnumerable<RoleViewModel> SelectedRoles { get; set; }
    }
4. Controller:
        [HttpPost]
        public ActionResult Add(GroupAddFacadeViewModel model, string[] Roles)
        {
            if (ModelState.IsValid)
            {
                //Do some work here
            }
        }
 
(Array of roles is posted correctly)
Best regards,
Max
AnswerRe: ModelState.IsValid is always false after post with checkboxlist datamemberMikhail Tsennykh2 Mar '13 - 13:08 
Hey Max,
 
This extension always posts an array of strings (it should be a part of a model object), since there is no other good way as of now, that is how html works...
 
To get your code working, instead of posting the whole view model to controller, try create a property on a view model that contains only things you need for your controller.
 
Try the following:
 
Adjust your view model like this:
public class GroupAddFacadeViewModel {
    public GroupAddViewModel Group { get; set; }
    public IEnumerable<RoleViewModel> Roles { get; set; }
 
    // Add this
    public PostedStuff PostedStuff { get; set; }
}
// Helper class to make posting back selected values easier
public class PostedStuff {
  public GroupAddViewModel Group { get; set; }
  public string[] Roles { get; set; }
}
Then change your controller like this:
[HttpPost]
public ActionResult Add(PostedStuff postedStuff) {
   if (ModelState.IsValid) {
      //Do some work here
   }
}
Then make sure only properties of 'PostedStuff' are included in the form being posted.
 
This recommendation is based on the documentation here:
http://mvccbl.com/Home/Documentation[^]
 
I hope that helps!
 
Regards,
Mikhail
GeneralRe: ModelState.IsValid is always false after post with checkboxlist data [modified]memberBMP_Mad_Max2 Mar '13 - 22:15 
Hi Mikhail,
Thanks a lot for help.
It works fine now.
Best regards
Max

modified 3 Mar '13 - 4:43.

GeneralRe: ModelState.IsValid is always false after post with checkboxlist datamemberMikhail Tsennykh3 Mar '13 - 4:42 
Awesome, I'm glad to hear that! Smile | :)
 
I believe that separating view model into separate ones will make everything more error-prone, since you'll always control what you post and what you don't, especially if your model/view will get more complicated e.g. if you include multiple forms on the same view, or have forms inside of the foreach loop, etc. I realized after few years of working with MVC3 and MVC4, it just makes life easier in the long run, even if it seems a bit more complicated at first.
 
Anyway, Good Luck with you project!
Mikhail
QuestionAuto-submit?memberSupermagle1 Mar '13 - 1:06 
I am using the CBL control to select filters for some displayed data. Is there an easy way to make the checkboxes automatically submit the form when checked/unchecked?
AnswerRe: Auto-submit?memberMikhail Tsennykh1 Mar '13 - 3:08 
The easiest way is to use jquery function like this:
$('input:checkbox').change(function() {
  $('#YOUR_FORM_ID').submit();
});
This will submit your form whenever any checkbox selection changes, so you might need to adjust jquery selector to target only required subset of checkboxes.
QuestionSteps to use thismemberPrashant Bhambar24 Feb '13 - 22:09 
Dear All,
 

Can you please provide the steps for how to use this,
as i am new to MVC. I have add the reference of the dll in my project but in
View Model it is not allowing me to use the CheckBoxList plz help it's very urgent.
 

Thanks
AnswerRe: Steps to use thismemberMikhail Tsennykh25 Feb '13 - 4:37 
Hi Prashant,
 
To make sure it is installed correctly I would suggest installing it from NuGet package manager[^], instead of adding the reference manually because the .dll attached to this article is for .NET 4.0 and MVC3 only.
 
If you have an MVC4 project with .NET 4.5 you need to install latest beta version, and the only way to do so is to install it from NuGet, you need to run this command in NuGet package manager console:
Install-Package MvcCheckBoxList -Pre  
Alternatively, if you don't want to use NuGet, you can download source project from Github[^], build it and copy MvcCheckBoxList.dll manually.
QuestionSome controller binding problemsmemberkwilder31 Jan '13 - 8:56 
I want to thank you for building this, it was much needed. I've gotten it to display the check boxes correctly, but I'm having a difficult time returning the posted values.
 
I went over the other threads with you and Alex Brown and my scenario is similar but I have an extra model which I think is causing the problems.
 
I need to pass more to the view than just the CheckBoxList data, so I've attached my CBLViewModel to a ViewData class that I pass to all views. I've looked at ALL your documentation and I still think I'm missing something somewhere.
 
Here are the various code snippets:
 
This is the view code:
 
@model PGO.Mvc.ViewData.OpticsItemViewData
 
... other HTML stuff here
 
<b>@Html.Label("Assign To")</b><br />
 
@Html.CheckBoxListFor(model => model.OpticsItemViewModel.PostedPages.PageIds,
    model => model.OpticsItemViewModel.AvailablePages,
    model => model.Id,
    model => model.PageName,
    model => model.OpticsItemViewModel.SelectedPages, Position.Vertical)
 
... other HTML stuff here
 
This is my ViewData class that passes any and all necessary data to the view:
 
public class OpticsItemViewData : BaseViewData
{
	public OpticsItemViewData()
	{
	    OpticsItemViewModel = new OpticsItemViewModel();
	}
	public OpticsItem OpticsItem { get; set; }
	public List<OpticsItem> OpticsItemList { get; set; }
	public SelectList PageSelectList { get; set; }
	public List<Page> PageList { get; set; }
	public OpticsItemViewModel OpticsItemViewModel { get; set; }
}
 
This is the ViewModel to be used by the CheckBoxList extension:
 
public class OpticsItemViewModel
{
	public IEnumerable<Page> AvailablePages { get; set; }
	public IEnumerable<Page> SelectedPages { get; set; }
	public PostedPages PostedPages { get; set; }
}
 
public class PostedPages
{
	public string[] PageIds { get; set; }
}
 
Here's part of my controller action with most of the non-CBL code stripped away. The PostedPages object is recognized Ok, but the PageIds property is always null.
 
[HttpPost]
public virtual ActionResult Create(
	[Bind(Exclude = "Id,rowversion", Prefix = "OpticsItem")]OpticsItem model, 
	[Bind(Prefix = "OpticsItemViewModel")]PostedPages postedPages, 
	IEnumerable<HttpPostedFileBase> attachments)
{
 
	var pageIds = postedPages.PageIds; // PageIds is always null!
	if (pageIds == null)
	    throw new Exception("No Pages were selected.");
 
}
 
And finally this is the rendered HTML so you can see what needs to be done in the controller:
<input id="OpticsItemViewModel_PostedPages_PageIds4" 
	name="OpticsItemViewModel.PostedPages.PageIds" 
	type="checkbox" value="1"></input>
	<label for="OpticsItemViewModel_PostedPages_PageIds4">48-Hour Optics</label><br/>
<input id="OpticsItemViewModel_PostedPages_PageIds5" 
	name="OpticsItemViewModel.PostedPages.PageIds" 
	type="checkbox" value="2"></input>
	<label for="OpticsItemViewModel_PostedPages_PageIds5">Glass Substrates</label><br/>
 
I know I'm missing something. Any help you can provide is appreciated.
 
Thanks,
 
King Wilder
AnswerRe: Some controller binding problemsmemberkwilder31 Jan '13 - 9:14 
This always seems to happen, the moment I post an issue, I figure it out myself.
 
Here's my solution, I just referenced the first part of the name attribute.
 
This was one of the checkbox input elements:
<input id="OpticsItemViewModel_PostedPages_PageIds4" 
	name="OpticsItemViewModel.PostedPages.PageIds" 
	type="checkbox" value="1"></input>
 
And here's how I referenced it in my controller:
[HttpPost]
public virtual ActionResult Create(
	[Bind(Exclude = "Id,rowversion", Prefix = "OpticsItem")]OpticsItem model, 
	OpticsItemViewModel opticsItemViewModel, // this is the new argument
	IEnumerable<HttpPostedFileBase> attachments)
{
 
	var pageIds = opticsItemViewModel.PostedPages.PageIds; // This worked!
	if (pageIds == null)
	    throw new Exception("No Pages were selected.");
 
}
 
Sorry to take up the bandwidth, but I hope this helps others.
 
Again, thanks for making this extension.
 
King Wilder
QuestionI am not able to use itmemberMember 273851422 Jan '13 - 0:35 
CheckBoxListFor was not recognizing my view model. I have added the dll in my reference, Am I missing anything ?
QuestionAdding an action link to each check box item?memberMichael Harper28 Nov '12 - 0:00 
Hello Mikhail
 
Thanks for the extension, it saved me a lot of time!
I was wondering, for each checkbox item generated how would I add an action link?
 
For example I have a list of modules and want the ability to click an edit link on each one:
 
    @Html.CheckBoxListFor( x => x.PostedModules.Modules,
                                 x => x.Modules,
                                 x => x.ModuleID,
                                 x => x.Title,
                                 x => x.SelectedModules
                                 
                                 )
 
Many thanks,
 
Michael
AnswerRe: Adding an action link to each check box item?memberMikhail Tsennykh28 Nov '12 - 3:56 
Hi Michael, thank you! I am glad it works for you!
 
At the moment the only way to accomplish what you want, is to use Display Templates, see example here (scroll down to 'Display templates to render html for checkbox' section):
http://mvccbl.com/Home/Examples[^]
 
Also note that Display Templates are only available in beta version 1.4.4.3-beta2, so if you use older version from this article, upgrade to it now:
Install-Package MvcCheckBoxList -Pre
Let me know if that works for you!
GeneralRe: Adding an action link to each check box item?memberMichael Harper28 Nov '12 - 5:54 
Thank you Mikhail I will let you know how it goes Smile | :)
Questionvertical_columns displaymemberAlvin Borgonia20 Nov '12 - 15:20 
I want to display the list in the following order:
 
1 2 3 4
5 6 7 8
 
I've already used Linq in the list but still it displays like this:
 
1 3 5 7
2 4 6 8
 
Thnaks.
QuestionRe: vertical_columns displaymemberMikhail Tsennykh21 Nov '12 - 3:25 
Did you try to use horizontal layout (default) instead of vertical? If you'd use horizontal, than you can try to limit the width of the <div> with your CheckBoxList inside, and browser will automatically arrange them in order.
 
Also reply here with a code of how you initialize extension currently, so it would be easier to help you.
QuestionRe: vertical_columns displaymemberAlvin Borgonia21 Nov '12 - 7:52 
Here is the code:
 
The CSS of my individual checkboxes.

 
label 
{
	display:inline-block;
}
 
.checkbox-normal
{
	display: none;
}
 
.checkbox-normal  +  label {
	background-color: #fafafa;
	border: 1px solid #cacece;
	box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05);
	padding: 9px;
	border-radius: 100%;
	display: inline-block;
	position:relative;
}
 

.checkbox-normal  + label:active, .checkbox-normal:checked + label:active {
	box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px 1px 3px rgba(0,0,0,0.1);
	width: 30px;
        height: 30px;
}
 
.checkbox-normal:checked + label {
	background-color: #e9ecee;
	border: 1px solid #adb8c0;
    	box-shadow: 0 1px 2px rgba(0,0,0,0.05), inset 0px -15px 10px -12px rgba(0,0,0,0.05), inset 15px 10px -12px rgba(255,255,255,0.1);
	color: #99a1a7;
}
 
.checkbox-normal:checked + label:after {
	content: '\2714';
	font-size: 14px;
	position: absolute;
	top: 8px;
	left: 12px;
	color: #99a1a7;
}
 
My Model
    public class RelocationModel
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public int Value { get; set; }
        public bool Selected { get; set; }
    }
 
    public class PostedRelocations
    {
        public string[] MetaIDs { get; set; }
    }
    
    public class ViewModel
    {
        public IList<RelocationModel> Relocations { get; set; }
        public IList<RelocationModel> SelectedRelocations { get; set; }
        public PostedRelocations PostedRelocations { get; set; }
 
        public IList<FamilySituationModel> FamilySituations { get; set; }
        public IList<FamilySituationModel> SelectedFamilySituations { get; set; }
        public PostedFamilySituations PostedFamilySituations { get; set; }
    }
 
    public class FamilySituationModel
    {
        public string Name { get; set; }
        public int Id { get; set; }
        public int Value {get;set;}
        public bool Selected { get; set; }
    }
 
    public class PostedFamilySituations
    {
        public string[] MetaIDs { get; set; }
    }
 
    
 
Now in my View
 
<table>
    <tr>
        <td>
        @{
        var htmlListInfo = new HtmlListInfo(HtmlTag.table, 5, new { @class = "styled_list" });
        <div class="editor-label">
        @Html.LabelFor(model => Model.Relocations)
        </div>
        <div class="editor-field">
        @Html.CheckBoxListFor(model => model.PostedRelocations.MetaIDs,
                        model => model.Relocations,
                        x => x.Id,
                        x => x.Value,
                        model => model.SelectedRelocations,
                         new { @class = "checkbox-normal" },
                        htmlListInfo, null, null)  
        </div>                        
        }
        </td>
    </tr>
</table>
 
The "Name" (e.g. Natural Disaster) in my model contains the description of the item in my list, while the "Value" (e.g 1) will hold the number which will be displayed as a label inside the checkbox.
 
What I want to do here is that I want to display the checkboxes in circles with the "Value" inside as a label and beside them would be the "Name" or the description. Would look like this:
1 Description 2 Description 3 Description
4 Desciption 5 Description 6 Description
 
The numbers are inside a circle (which is the checkbox) and the description beside them.
I would very much appreciate it if anyone could help me on this. Big Grin | :-D
 

Thank you very much
AnswerRe: vertical_columns displaymemberMikhail Tsennykh21 Nov '12 - 8:44 
Well first of all, to get your list aligned horizontally, you need to get rid of HtmlListInfo and call it like that:
@Html.CheckBoxListFor(model => model.PostedRelocations.MetaIDs,
                      model => model.Relocations,
                      x => x.Id,
                      x => x.Value,
                      model => model.SelectedRelocations,
                      new { @class = "checkbox-normal" })
This will effectively allign them like, if width is limited by wrapping div around list:
1 2 3 4
5 6 7 8
 
So try that first.
 
As for:
"The numbers are inside a circle (which is the checkbox) and the description beside them"
As of now this would be somewhat challenging to achieve and will involve heavy reliance on JQuery.
 
At current state of this extension the best way to customize output is to use Display Templates, see example here (scroll down):
http://mvccbl.com/Home/Examples[^]
 
However right now you can use Display Templates only for HtmlTag.vertical_columns and HtmlTag.table, so no horizontal layout yet. After your question, I figured that I need to add support for horizontal layout when using Display Templates, but I'll have to work on that one of those days.
 
Finally, since you need quite customized output, I would suggest to try to generate checkbox list manually, as I feel It'll be less difficult than making this extension work for your needs.
 
Anyway first try what I suggested above.
QuestionNull returning during postmemberAnish71420 Nov '12 - 8:41 
Controller:
public ActionResult InventorySnapshot(InventorySnapshotViewModel viewModel)
 {
     return ExecuteGenericAction(viewModel, x => new InventorySnapshotAction());
 }
 
Model
public class InventorySnapshotViewModel
{
public IEnumerable<ProductAttribute> ProductAttributes { get; set; }
 
    public IEnumerable<ProductAttribute> SelectedProductAttributes { get; set; }
 
}
 
public class ProductAttribute
{
    public int ID { get; set; }
 
    public string Name { get; set; }
}
 
@Html.CheckBoxListFor(x => x.ProductAttributes, x => x.ProductAttributes, x => x.ID, x => x.Name, x => x.SelectedProductAttributes)
 
However, SelectedProductAttributes is null during post. Other values in the form are populated. Any help is appreciated.
AnswerRe: Null returning during postmemberMikhail Tsennykh20 Nov '12 - 9:12 
Well, unfortunately checkbox list only posts to an array of strings, not to a public property. That is a default MVC functionality, so you should have a property of type string[] and a name of ProductAttributes as one of the controller's parameters. Similar question was discussed and resolved in previous conversation here:
http://www.codeproject.com/Messages/4420615/Re-Posting-model-back-doest-contain-selected-items.aspx[^]
 
Also in order to create advanced setup, similar to yours, see detailed examples here:
http://mvccbl.com/Home/Examples[^]
Try to adjust your model/controllers to work in a similar way.
 
Let me know how it goes!
GeneralPosting model back does't contain selected itemsmemberalexjamesbrown5 Nov '12 - 6:50 
I'm having trouble getting the selected values into my model.
 
I pass in a view model that looks like:
 
    public class NewLicenseViewModel
    {
        public NewLicenseModel NewLicense { get; set; }
        public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
    }
 
LicensableFeatureModel is a simple:
 
public class LicensableFeatureModel
{
    public string ID { get; set; }
    public string Name { get; set; }
}
My MVC razor view looks like:
 
@model Licensing.Web.Models.NewLicenseViewModel
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
                   x => x.AvailableLicensableFeatures,
                   x => x.ID,
                   x => x.Name,
                   x => x.NewLicense.LicensedFeatures)
 
 
The checkboxes are appearing correctly.
 
However, when I post the form, my controller action receives the NewLicenseModel with other bits filled in (in other parts of form) however, .LicensedFeatures is null:
 
[HttpPost]
public ActionResult Create(NewLicenseModel licenseRequest)
{
    //license.LicensedFeatures is null here :-(
}
 
Any idea what I've done wrong?
AnswerRe: Posting model back does't contain selected itemsmemberMikhail Tsennykh5 Nov '12 - 8:56 
Here you go:
 
1) When values of selected checkboxes are posted back to controller, they are posted as an array of strings only, and cannot be mapped to a class directly, so your model:
public class NewLicenseViewModel {
  public NewLicenseModel NewLicense { get; set; }
  public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
}
Should look like this:
public class NewLicenseViewModel {
  public NewLicense NewLicense { get; set; }
}
public class NewLicense {
  public string[] LicensedFeatures { get; set; }
}
2) Then first part of your CBL name (NewLicense) must match controller parameter, and second part (LicensedFeatures) must match parameter of a class NewLicense:
[HttpPost]
public ActionResult Create(NewLicense newLicense) {
  // now you can get a list of selected values like this:
  var selectedValues = newLicense.LicensedFeatures;  
  // todo: map selected values to your data class
}
 
3) Remember that it is very important to match the pattern above for your call to checkbox control to work (again, 'NewLicense' is a name of a property on the view model, 'LicensedFeatures' name of a property of class 'NewLicense'):
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
                   x => x.AvailableLicensableFeatures,
                   x => x.ID,
                   x => x.Name,
                   x => x.NewLicense.LicensedFeatures)
 
Please see more examples of this pattern here:
http://mvccbl.com/Home/Examples[^]
 
Hope that helps!
 
Regards,
Mikhail
GeneralRe: Posting model back does't contain selected itemsmemberalexjamesbrown5 Nov '12 - 23:47 
I have followed this to the letter, however it is giving me an error on CheckBoxListFor :
 
Compiler Error Message: CS0411: The type arguments for method 'MvcCheckBoxList_Extensions_Model.CheckBoxListFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>>, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>, System.Linq.Expressions.Expression>>, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
 
Also, in your example above, you seem to switch between NewLicense and NewLicenseModel..
 

 
Now, I have:
 
public class NewLicenseViewModel
{
    public NewLicenseModel NewLicense { get; set; }
 
    public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
}
public class NewLicenseModel
{
    public string SomeProperty { get; set; }
 
    public string[] LicensedFeatures { get; set; }
}
 
And finally in my view:
 
@model Licensing.Web.Models.NewLicenseViewModel
@Html.CheckBoxListFor(x=>x.,
                   x => x.AvailableLicensableFeatures,
                   x => x.ID,
                   x => x.Name, 
                   x => x.NewLicense.LicensedFeatures)
 
Controller looks like:
 
[HttpPost]
public ActionResult Create(NewLicenseModel licenseRequest)
{

AnswerRe: Posting model back does't contain selected itemsmemberMikhail Tsennykh6 Nov '12 - 3:33 
For your setup to work you need to change checkbox list call (add name property):
@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures, // the name property has to be set like this
                                                          // for check box list to post correctly
                      x => x.AvailableLicensableFeatures,
                      x => x.ID,
                      x => x.Name, 
                      x => x.NewLicense.LicensedFeatures)
Than change the name of the parameter for controller to newLicense:
[HttpPost]
public ActionResult Create(NewLicenseModel newLicense){
  // use your data:
  string[] selectedValues = newLicense.LicensedFeatures;
}
 
Let me explain how it works in more detail -
 
1) The name of checkboxlist selected is NewLicense.LicensedFeature, and that creates a set of checkboxes on html output looking something like this:
<input id="NewLicense.LicensedFeatures1" name="NewLicense.LicensedFeatures" type="checkbox" value="1" >
<input id="NewLicense.LicensedFeatures2" name="NewLicense.LicensedFeatures" type="checkbox" value="2" >
<input id="NewLicense.LicensedFeatures3" name="NewLicense.LicensedFeatures" type="checkbox" value="3" >
2) Then when you check some and post them back the default MVC convention matches first part of the name property NewLicense to the matching name of controller parameter, newLicense in our case. Name is not case sensitive, but it has to match exactly.
3) Next it will try to match an array of LicensedFeatures to a similar named property of class NewLicenseModel which is a string array of LicensedFeatures.
 
Try that, it should work now!
GeneralRe: Posting model back does't contain selected itemsmemberalexjamesbrown6 Nov '12 - 3:48 
Sorry, there was an error in my previous post.
That's exactly how I have it in my view, however it's throwing an error there...
 
See this for example:
http://i.imgur.com/Ze6zC.png
AnswerRe: Posting model back does't contain selected itemsmemberMikhail Tsennykh6 Nov '12 - 4:27 
Oh I see it now, sorry I missed this error at first:
The values selected has to be of the same type as source data values: IEnumerable<LicensableFeatureModel>
 
So your model and call to checkbox list should be this:
public class NewLicenseViewModel
{
    public NewLicenseModel NewLicense { get; set; }
    public IEnumerable<LicensableFeatureModel> AvailableLicensableFeatures { get; set; }
    public IEnumerable<LicensableFeatureModel> SelectedLicensableFeatures { get; set; }
}
 
// and call to create list:

@Html.CheckBoxListFor(x => x.NewLicense.LicensedFeatures,
                      x => x.AvailableLicensableFeatures, // source data
                      x => x.ID,
                      x => x.Name, 
                      x => x.SelectedLicensableFeatures)  // should be same type as source data
Hope it will work now!
GeneralRe: Posting model back does't contain selected itemsmemberalexjamesbrown15 Nov '12 - 12:15 
Sorted
Thanks
QuestionHtmlTag.ulmemberMember 951728515 Oct '12 - 21:55 
The ul is not present in the HtmlTag enumeration, is that correct?
AnswerRe: HtmlTag.ulmemberMikhail Tsennykh16 Oct '12 - 3:12 
Yes, it was removed since version 1.4.3.0. See the reason here: https://github.com/mikhail-tsennykh/MVC3-Html.CheckBoxList-custom-extension/issues/4[^]
 
If you still prefer to use HtmlTag.ul, you can install older version of extension from NuGet:
Install-Package MvcCheckBoxList -Version 1.4.2.3

GeneralRe: HtmlTag.ulmemberMember 951728517 Oct '12 - 20:33 
Then please update the documentation for the latest version.
AnswerRe: HtmlTag.ulmemberMikhail Tsennykh18 Oct '12 - 3:24 
Yepp, I'll definitely update this article once latest beta version is finalized, since there will be few breaking changes.
QuestionCan a Guid be used instead of intmemberraspa2k19 Sep '12 - 10:47 
public class ContentCategoryDO
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }
 
public class ContentViewModel
{
public string Contents { get; set; }
        public ICollection<Guid> CategoryIds { get; set; }
        public ICollection<ContentCategoryDO> Categories { get; set; }
}
 
When I try this
@Html.CheckBoxListFor(m => m.CategoryIds,
                                                m => m.Categories,
                                                m => m.Id,
                                                m => m.Name,
                                                m => m.CategoryIds
                                            )
the Id and Name are in red and when I mouse over the CheckBoxListFor I get the message "The type arguments for method 'MvcHtmlString MvcCheckBoxList_Extensions_Model.CheckBoxListFor
QuestionRepopulate listmemberMember 941933210 Sep '12 - 6:48 
Sorry if someone's already addressed this but I was wondering if CheckBoxListFor has a mechanism for refreshing the items in the list. Simple scenario is this: show user a list of available options as checkboxes using your CheckBoxListFor; separately, I also provide an 'Add' button in case a value the user needed to check is not already in the list; they save the new item (probably through an ajax post) then need to get handle on CheckBoxListFor to repopulate checkboxes so new item shows up. Thoughts?
AnswerRe: Repopulate listmemberMikhail Tsennykh10 Sep '12 - 8:48 
For right now there is nothing like that built-in. This extension is a primarily server-side control with deep tie into the MVC ViewModel. At the current state it won't be practical to make it work in this way.
 
However, I see two ways to achieve what you need:
 
1) Easier way - it should be fairly simple to achieve that functionality by first posting new value to 'Add' via ajax call to a specific controller, than if this call returns successful result, reload the page via javascript, so that new value is added to the list.
 
2) A bit harder way - 'Add' new option to database via ajax call to a controller (like in #1) than, if that was successful, append checkbox html code to the list via jquery similar to that (so you won't need to reload the page):
$('.checkBoxList label:last').append('<input id="ID" type="checkbox" value="VALUE"><label for="ID">CHECKBOX_TEXT/label>');
Where .checkBoxList is a class of a <div> which wraps around the control.
NewsDevelopment version 1.4.4.0 published on GithubmemberMikhail Tsennykh25 Aug '12 - 6:01 
Just pushed latest dev version 1.4.4.0 to github:
https://github.com/mikhail-tsennykh/MVC3-Html.CheckBoxList-custom-extension/tree/dev[^]
(do not use in production!)
 
Among other changes it now includes templating code by emillium[^], and implementation of boolean selector and dynamic tags proposed by cactussss[^].
 
Another major change is that I removed all .CheckBoxList overloads so only .CheckBoxListFor are used now. Also I introduced new internal class listConstructor which simplifies how overloads pass the data to ListBuilder.
 
Those are not all the changes I wanted for the new version, but they are the base ones.
 
Next big thing will be a cleanup and applying more single-responsibility to ListBuilder class, adding more examples to sample site, and some other stuff I haven't thought of yet))
GeneralRe: Development version 1.4.4.0 published on Github [modified]membercactussss25 Aug '12 - 14:38 
Overall good release. Couple things though:
1. I am definatelly against this change: "I removed all .CheckBoxList overloads". There is a good reason these kind of overloads are included in MVC out of the box. Occasionally, POST model may differ from the GET model used to render a view. In such scenario TextBox(...) would be used instead of TextBoxFor(...).
 
2. It appears overload #13 has a bug (or I just don't understand how it should work).
Please try using following code:
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs,
		x => x.AvailableCities,
		x => x.Id,
		x => x.Name,
		x => Model.SelectedCities.Any(s => x.Id == s.Id),
                new { @class = "MainHtmlAttrs" },
                new HtmlListInfo(HtmlTag.vertical_columns, 1),
		null,
		null)
I could not find any items on the rendered page with class "MainHtmlAttrs".
Further testing showed that the last null is what prevents class "MainHtmlAttrs" to appear.

modified 25 Aug '12 - 22:10.

AnswerRe: Development version 1.4.4.0 published on GithubmemberMikhail Tsennykh27 Aug '12 - 3:46 
Great, thank you!
 
#1.
Well, here is my reasoning for removal of .CheckBoxList overloads, I removed them because they mostly had just duplicate code as a .CheckBoxListFor except for using string as name of the list, which I figured would be easy to customize just by adding another empty property to the model (e.g. public object MyCustomCheckboxListName { get; set; }), and with addition of singular (boolean) selector it would make the extension have 4 similar overloads for each level, which will be harder to maintain... Here is the example of what I mean:
@Html.CheckBoxListFor(x => x.CustomListName,
		      x => x.AvailableCities,
		      x => x.Id,
		      x => x.Name,
		      x => null)
Where CustomListName is this model property use just to generate name (name="CustomListName"):
public object CustomListName;
 
#2.
To make overload work do this:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs,
		      model => model.AvailableCities,
		      entity => entity.Id,
		      entity => entity.Name,
		      entity => Model.SelectedCities.Any(s => entity.Id == s.Id),
                      new { @class = "MainHtmlAttrs" },
                      new HtmlListInfo(HtmlTag.vertical_columns, 1),
		      null,
		      model => null)
You basically just add x => (model =>) in front of last null and it will render the tag, since it wants an expression.
Also if both last two values are null, you can use this instead:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs,
		      entity => entity.AvailableCities,
		      entity => entity.Id,
		      model => model.Name,
		      x => Model.SelectedCities.Any(s => x.Id == s.Id),
                      new HtmlListInfo(HtmlTag.vertical_columns, 1),
                      entity => new { @class = "MainHtmlAttrs" })
What do you think?
GeneralRe: Development version 1.4.4.0 published on Githubmembercactussss27 Aug '12 - 6:00 
#1.
Your use of listConstructor does a good job of making sure no code would be duplicated. The only thing that would look like duplicate is the call to _listBuilder.CheckBoxList(...), but that's OK since it's a new overload.
 
I understand that maintenance is a hassle sometimes, but that should not get in a way of functionality of the extension. Having dummy properties on the model is unclean and inelegant code.
 
Having said that I propose placing all CheckBoxListFor overloads in a single file (example: CheckBoxListForOverloads.cs) and working only on these during development. When ready to release, just do these 4 steps:
------------------------------------------------------
1. copy all these extensions into a new file (example: CheckBoxListOverloads.cs)
2. modify their name from CheckBoxListFor to CheckBoxList.
3. rename Expression<Func<TModel, TProperty>> listNameExpr into string listName
4. change listName = listNameExpr.toProperty() to listName = listName
------------------------------------------------------
These 3 steps will take you 3 minutes and you only have to perform them when you are ready for a new release which takes care of maintenance issue.
 
I have to go to work now and will examine #2 when I come back.

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 6 May 2013
Article Copyright 2011 by Mikhail Tsennykh
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid