0

I got the following code from the internet for CheckboxListFor html helper extension. At the moment, in the SelectedValues it is returning a List<string> of selected values from the checkboxlist. I want to get a comma-separated string in SelectedValues.

Can anyone tell me how I can achieve it?

Here is the code:

HTMLHelper extension:

        /// <summary>
    /// Returns a checkbox for each of the provided <paramref name="items"/>.
    /// </summary>
    public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, string listName, IEnumerable<SelectListItem> items, object htmlAttributes = null)
    {
        var container = new TagBuilder("div");
        foreach (var item in items)
        {
            var label = new TagBuilder("label");
            label.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);

            var cb = new TagBuilder("input");
            cb.MergeAttribute("type", "checkbox");
            cb.MergeAttribute("name", listName);
            cb.MergeAttribute("value", item.Value ?? item.Text);
            if (item.Selected)
                cb.MergeAttribute("checked", "checked");

            label.InnerHtml = cb.ToString(TagRenderMode.SelfClosing) + item.Text;

            container.InnerHtml += label.ToString();
        }

        return new MvcHtmlString(container.ToString());
    }

    private static IEnumerable<SelectListItem> GetCheckboxListWithDefaultValues(object defaultValues, IEnumerable<SelectListItem> selectList)
    {
        var defaultValuesList = defaultValues as IEnumerable;

        if (defaultValuesList == null)
            return selectList;

        IEnumerable<string> values = from object value in defaultValuesList
                                     select Convert.ToString(value, CultureInfo.CurrentCulture);

        var selectedValues = new HashSet<string>(values, StringComparer.OrdinalIgnoreCase);
        var newSelectList = new List<SelectListItem>();

        selectList.ForEach(item =>
        {
            item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
            newSelectList.Add(item);
        });

        return newSelectList;
    }

    /// <summary>
    /// Returns a checkbox for each of the provided <paramref name="items"/>.
    /// </summary>
    public static MvcHtmlString CheckBoxListFor<TModel, TValue>(this HtmlHelper<TModel> htmlHelper, 
        Expression<Func<TModel, TValue>> expression, 
        IEnumerable<SelectListItem> items, object htmlAttributes = null)
    {
        var listName = ExpressionHelper.GetExpressionText(expression);
        var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

        items = GetCheckboxListWithDefaultValues(metaData.Model, items);
        return htmlHelper.CheckBoxList(listName, items, htmlAttributes);
    }

In the view:

@Html.CheckBoxListFor(model => model.SelectedValues, Model.MySelectList)

Model:

public class MyViewModel
{        
      public SelectList MySelectList{ get; set; }

      public List<string> SelectedValues{ get; set; }

      //public string SelectedValues{ get; set; }   Can I get comma separated string here
}

Note that I need comma separated string returned from the helper not after I got back list on the controller action.

Why I am trying to do this?:

//Here in my model, I am getting `SelectedValues` which is a List<String>.
public ActionResult Index(MyViewModel model)
{
      //My code....
}

In View

//But I cannot save this list into RouteValueDictionary like:
var searchCriteria = new RouteValueDictionary();
searchCriteria["model.SelectedValues"] = Model.SelectedValues; // List<string> cannot be save here. That's why I needed comma separated string.
var viewDataDictionary = new ViewDataDictionary();
viewDataDictionary["searchCriteria"] = searchCriteria;

@Html.Partial("_MyPagingView", Model.MyList, viewDataDictionary)

There is a whole mechanism inside the _MyPagingView which calls Index Action whenever next page is clicked. And to preserve the state of the search we need to keep our searched data inside RouteValueDictionary.

10
  • String.Join? Commented Apr 2, 2015 at 5:33
  • Where to put string.join? Note that I need comma separated string returned from the helper not after I got back the list. Commented Apr 2, 2015 at 5:35
  • You helper is generating a series of checkboxes with the same name. It can only post back and array or values. You need to generate the comma separated string on the server, or use javascript to build the string and update a hidden input before you post. Commented Apr 2, 2015 at 5:38
  • @UsmanKhalid you can use string.Join in the controller action Commented Apr 2, 2015 at 5:40
  • @StephenMuecke I am already using javascript and hidden value. I was just curious to find out if I can get it without extra javascript code. Commented Apr 2, 2015 at 5:42

2 Answers 2

1

You could create a helper method to add theSelectedValues to aRouteValueDictionary

public void AddRoutes(List<string> values, string propertyName, RouteValueDictionary dictionary)
{
    for (int i = 0; i < values.Count; i++ )
    {
        string key = string.Format("{0}[{1}]", propertyName, i);
        dictionary[key] = values[i];
    }
}

and then use it as

var searchCriteria = new RouteValueDictionary();
AddRoutes(Model.SelectedValues, "SelectedValues", searchCriteria);

and avoid the need to create a hidden input and use javascript

Sign up to request clarification or add additional context in comments.

Comments

0

I prefer changing the code of your view model:

public class MyViewModel
{
    public SelectList MySelectList{ get; set; }

    public List<string> SelectedValues { get; set; }

    public string SelectedString
    {
        get
        {
            if (SelectedValues == null) return "";
            return string.Join(",", SelectedValues);
        }
        set
        {
            if (!string.IsNullOrEmpty(value))
            {
                SelectedValues = value.Split(',').ToList();
            }
        }
    }
}

You can get the comma seperated string :

//In controller
var selected = model.SelectedString; 

//In view
searchCriteria["model.SelectedValues"] = Model.SelectedString;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.