What is it?
It is a custom extension of Microsoft MVC Framework's HtmlHelper
class,
which creates a postable Model-based list of check boxes.
It was created because there is no built-in MVC way to do this at all (including MVC4).
Features:
- Easy to use
- Creates POSTable checkboxes from any set of data
- Strongly-typed, based on View Model
- Extensive control over layout and appearence
- Right-to-left language support
- Open source (CPOL License)
See it in action:
@Html.CheckBoxListFor(model => model.CheckBoxListName, model => model.ListOfYourData, entity => entity.FieldToUseAsCheckBoxValue, entity => entity.FieldToUseAsCheckBoxName, model => model.ListOfYourSelectedData)
Install it
Source it
< >
Learn it
Discuss it
Examples
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 */); }
We can use examples below to create our checkbox list:
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, // checkbox list name, 'PostedCities.CityIDs' in this case x => x.AvailableCities, // List<City>() x => x.Id, // City.Id x => x.Name, // City.Name x => x.SelectedCities) // List<City>() - should contain only cities to be selected
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, // Checkbox list name, 'PostedCities.CityIDs' in this case x => x.AvailableCities, // List<City>() x => x.Id, // City.Id x => x.Name, // City.Name x => x.IsSelected) // City.IsSelected - boolean property in the database
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, // Checkbox list name, 'PostedCities.CityIDs' in this case x => x.AvailableCities, // List<City>() x => x.Id, // City.Id x => x.Name, // City.Name x => selectedIds.Contains(x.Id)) // Linq query returns bool if item Id matches the list
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, x => x.AvailableCities, x => x.Id, x => x.Name, x => x.SelectedCities, Position.Vertical)
Some cities will have custom tags from database: ('new {what = "smallCity"}' for Monroe, and 'new {what = "bigCity"}' for Moscow)
We have this jquery code which will apply to certain custom tags from db:
$('[what="smallCity"]').css("color", "blue"); $('[what="bigCity"]').css("color", "green");And we call the control like this:
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, x => x.AvailableCities, x => x.Id, x => x.Name, x => x.SelectedCities, x => x.Tags) // Tags is a database/model field of type 'object' // with value similar to: 'new {tagName = "tagValue"}' // they will be merged with other tags and applied to checkbox and its label
First you need to create Views\Shared\DisplayTemplates\City.cshtml
file to hold a template for our base class
City
.
It must have same name as class City
for which it templates,
and must have a @model
set to use City
(including applicable namespace).
@model MvcCheckBoxListSampleApp.Model.City <strong>@Model.Name</strong> - text from display template
var htmlListInfo = new HtmlListInfo(HtmlTag.vertical_columns, 2, null, TextLayout.Default, TemplateIsUsed.Yes); @Html.CheckBoxListFor(model => model.PostedCities.CityIDs, model => model.AvailableCities, city => city.Id, city => city.Name, model => model.SelectedCities, htmlListInfo)
We have this style for each checkbox:
.styled_checkbox { background: wheat; cursor:pointer; border-radius:5px; margin: 3px; padding: 0px 5px; }Also we have this style for the list wrapper (applies to each column):
.styled_list { color:green; background:lightblue; border-radius:5px; margin-right: 15px; padding:3px 5px 3px 5px; line-height: 25px; }And we apply them below:
@{ var htmlListInfo = new HtmlListInfo(HtmlTag.vertical_columns, 2, new { @class="styled_list" }; @Html.CheckBoxListFor(x => x.PostedCities.CityIDs, x => x.AvailableCities, x => x.Id, x => x.Name, x => x.SelectedCities, new { @class="styled_checkbox" }, // additional html attributes (for each checkbox and label) htmlListInfo), // formatting new[] {"3", "5", "7"}, // disabled values x => x.Tags) // html tags from database }
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, x => x.AvailableCities, x => x.Id, x => x.Name, x => x.SelectedCities, Position.Vertical_RightToLeft)
@Html.CheckBoxListFor(x => x.PostedCities.CityIDs, x => x.AvailableCities, x => x.Id, x => x.Name, x => x.SelectedCities, new HtmlListInfo(HtmlTag.vertical_columns, 0, null, TextLayout.RightToLeft))
Documentation
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 */); }
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
@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
And in our example it looks 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:
If we have a list of selected values on our View -var selectedIds = new List<int> { 1, 3, 5 };
it'll look like this:
@Html.CheckBoxListFor(model => model.PostedCities.CityIDs, model => model.AvailableCities, entity => entity.Id, entity => entity.Name, entity => selectedIds.Contains(entity.Id))where
selectedIds.Contains(entity.Id)
returns bool if item Id matches the list
Since five base properties 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 combosor 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)
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 combosor 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
For more information and discussion see
Contributors
-
Sacha Barber
Since version 1.2+, portions of his code are used in this extension
(source: http://sachabarber.net/?p=1007) -
Joshua Russo
Since version 1.4+, portions of code from his version of this control are used in this extension
(source: https://docs.google.com/leaf?id=0BwPweK...) -
Todd (Emillium)
Enhancement to use Display Template
(source: http://www.codeproject.com/Messages/4337526/Re-Enhancement-to-use-Display-Template.aspx) -
Dmitry A. Efimenko
Boolean checkbox selector and other ideas
(source: http://www.codeproject.com/Messages/4331311/Possible-updates.aspx)