DropDown
The new overrides of the DropDown helper defined in the Mvc Controls Toolkit allow separate styling of each item, grouping of items with the <optgroup> tag, and the fields to be used as value and text fileds can be specified through lamda expressions(thus,
taking advantage o syntactic checks and Visual Studio IntelliSense), instead of strings.
The above advantages are achieved by substituting the usual SelectList
parameter with the ChoiceList parameter used also by the
CeckBox list and by the DualSelect Box:
ChoiceListHelper.Create( RegisterModel.AllRoles,(t => t.Code), (t => t.Name))
The first parameter is the List whose elements contain the fields to be used as value field and text field for all <option>s of the select. The first lambda expression defines the value field while the second lambda expression defines the
text field.
In order to style each item separatetly one can add a third lambda expression that, given an item, returns either an anonymous object or an
IDictionary that defines the attributes of the item:
ChoiceListHelper.Create(RegisterModel.AllRoles,
m => m.Code,
m => m.Name,
m => new
{
style = m.Code % 2 == 0 ?
"color:Blue; background-color:White" :
"color:Red; background-color:White"
})
The above definition causes odd and even items to be styled differently.
There is no ListBox helper analogous to the DropDown override described above, simply beacuse the DropDown helper is smart enough to understand we passed it a List, instead of a single value, and in such a case it behaves like a multiselect.
If also all list items are contained in some property of the ViewModel, we can specify them through a lambda expression with the HtmlHelper extension:
public static ChoiceList<TItem, TValue, TDisplay>
CreateChoiceList<VM, TItem, TValue, TDisplay>(
this HtmlHelper<VM> htmlHelper,
Expression<Func<VM, IEnumerable<TItem>>> expression,
Expression<Func<TItem, TValue>> valueSelector,
Expression<Func<TItem, TDisplay>> displaySelector,
Func<TItem, object> labelAttributesSelector = null,
Func<TItem, object> valueAttributesSelector = null,
bool usePrompt = true,
string overridePrompt = null)
Attention: when this extension method is called either by dropd down or list box within a
Client Block, all list items of the dropdown or list box are automatically bound to the property referenced by the lambda expression on the client side.
If we want all items to be grouped according to the value of another item field, we have to provide two more lambda expressions: the first one returns the values to be used for the grouping, while the second one returns the text to be displayed in
the <optgroup> the item belong to:
ChoiceListHelper.CreateGrouped(RegisterModel.AllRoles,
m => m.Code,
m => m.Name,
m => m.GroupCode,
m => m.GroupName,
m => new {style="color:White; background-color:Black"},
m => new { style = m.Code%2 == 0 ?
"color:Blue; background-color:White":
"color:Red; background-color:White"} )
We provided also the lamda expressions that define respectively the style of each optgroup, and the style of each item. The whole code for displaying amultiselect is:
<%: Html.DropDownListFor(m => m.Roles2,
new {style="height:100px"},
ChoiceListHelper.CreateGrouped(RegisterModel.AllRoles,
m => m.Code,
m => m.Name,
m => m.GroupCode,
m => m.GroupName,
m => new {style="color:White; background-color:Black"},
m => new { style = m.Code%2 == 0 ?
"color:Blue; background-color:White":
"color:Red; background-color:White"} ))
%>
Where Roles2 is a list of role Codes, and the secon argument defines the style of the multiselect as a whole.
Below the result:

Both ChoiceListHelper.Create and ChoiceListHelper.CreateGrouped allows two optional parameters, namely:
bool usePrompt = true,
string overridePrompt=null
If the property to display is not a list and consequentely the control doesn' displays as a multiselect, a prompt is provided as first element of the DropDown automatically if
usePrompt=true, and if either overridePrompt != null or a prompt is defined in a Data Annotation:
[Display(Name="Roles in Blog", Prompt = "Choose a Role")]
public int SingleRole { get; set; }
overridePrompt, if provided, overrides the prompt of the Data Annotation.
The value attribute of the prompt item is the empty string, and, as a consequence, it may trigger a Required Attribute. If a function to compute the style of each item is passed as parameter to either ChoiceListHelper.Create or ChoiceListHelper.CreateGrouped it
is called with a null paarameter to yield the html attributes of the prompt item.
For instance the code below:
<%: Html.DropDownListFor(m => m.SingleRole,
ChoiceListHelper.CreateGrouped(RegisterModel.AllRoles,
m => m.Code,
m => m.Name,
m => m.GroupCode,
m => m.GroupName,
m => new {style="color:White; background-color:Black"},
m => {
if (m == null)
return new
{
@class = "watermark"
};
else
return new
{
style = m.Code % 2 == 0 ?
"color:Blue; background-color:White" :
"color:Red; background-color:White"
};
}))
%>
<%: Html.ValidationMessageFor(m => m.SingleRole, "*") %>
yields:

All items of a DropDown can be dynamically provided or substitued by calling the javascript function:
MvcControlsToolkit_UpdateDropDownOptions(url, jTarget, prompt, optionsCss, optGroupsCss)
Where:
- url is the url of the action method that will provided the items in jSon format. The url can include also query string parameters.
- jTarget is a jQuery object that selects all DropDowns whose items will be replaced.
- prompt, if provided, is a string to be used as prompt for the DropDowns.
- optionsCss, optGroupsCss are Css classes to be applied respectively to the newly created option elements and to the newly created optgroup elements. Each of them can be also a function that accepts as input the value of the option
or optgroup and return a Css class.
The action method, must return the result of calling the PrepareForJson method o a
ChoiceList object, translated into jSon, as shown in the example below:
<select id="dynamicSelect"> </select><input id="btnDynamicSelect" type="button" value="Populate dropdown" />
<script type="text/javascript">
$('#btnDynamicSelect').click(function () {
MvcControlsToolkit_UpdateDropDownOptions('<%:Url.Action("AvailableRoles", "Account") %>', $('#dynamicSelect'), 'Choose Role', function (x) {return x == '' ? 'watermark': 'normal' }, "inverted");
});
</script>
public ActionResult AvailableRoles()
{
var res=Json(MVCControlsToolkit.Controls.ChoiceListHelper.CreateGrouped(RegisterModel.AllRoles,
m => m.Code,
m => m.Name,
m => m.GroupCode,
m => m.GroupName).PrepareForJson(), JsonRequestBehavior.AllowGet);
return res;
}
Obviously the action method can have also parameters that to be passed through the
url parameter of the MvcControlsToolkit_UpdateDropDownOptions function.
If also all list items are contained in some property of the ViewModel, we can specify them through a lambda expression with the HtmlHelper extension:
public static ChoiceList<TItem, TValue, TDisplay>
CreateGroupedChoiceList<VM, TItem, TValue, TDisplay, TGroup, TDisplayGroup>(
this HtmlHelper<VM> htmlHelper,
Expression<Func<VM, IEnumerable<TItem>>> expression,
Expression<Func<TItem, TValue>> valueSelector,
Expression<Func<TItem, TDisplay>> displaySelector,
Func<TItem, TGroup> groupValueSelector,
Func<TItem, TDisplayGroup> groupDisplaySelector,
Func<TItem, object> groupAttributesSelector = null,
Func<TItem, object> labelAttributesSelector = null,
Func<TItem, object> valueAttributesSelector = null,
bool usePrompt = true,
string overridePrompt = null)
Attention: when this extension method is called either by dropd down or list box within a Client Block, all list items of the dropdown or list box are automatically bound to the property referenced by the lambda expression
on the client side.