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:

drop down prompt

All items of a DropDown can be dynamically provided or substitued by calling the javascript function:

mvcct.widgets.ajaxDropDown.update(url, jTarget, prompt, optionsCss, optGroupsCss) version >= 3.0.0

MvcControlsToolkit_UpdateDropDownOptions(url, jTarget, prompt, optionsCss, optGroupsCss) version < 3.0.0

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.

Last edited Jun 22, 2014 at 11:51 AM by frankabbruzzese, version 10

Comments

No comments yet.