Asp.net-mvc – ASP.NET MVC (razor) Listbox multiselect values to string

asp.net-mvcrazor

I have two multi-select list boxes; one with months and one with years such as the following:

@Html.ListBoxFor(m => m.IncludeGuestsArrivedInTimeframeMonths, Model.TimeframeMonths)
@Html.ListBoxFor(m => m.IncludeGuestsArrivedInTimeframeYears, Model.TimeframeYears)

I'm saving the both values to the database as a comma separated list (string/nvarchar). The values are being like this: Months: 1,3,7; Years: 2002,2005

For some reason when I pull the values back out to the form, the months are pre-selecting in the listbox fine, but the years are not.

Any ideas?


EDIT – Additional code samples:

Controller – Manage

public ActionResult Manage(Guid id)
    {
        var list = _listService.GetList(id);

        var model = LoadModelFromObject(list);
        model.TimeframeMonths = GenerateMonthDropdown();
        model.TimeframeYears = GenerateYearDropdown(model.IncludeGuestsArrivedInTimeframeYears.Split(','));
        model.DaysOfWeek = GenerateDaysOfWeekDropdown();

        return View(model);
    }

Controller – 'Helper'

private IList<SelectListItem> GenerateYearDropdown(string[] selected)
    {
        var list = new List<SelectListItem>();

        var startYear = DateTime.Now.Year - 10;

        for (int idx = startYear; idx < startYear + 11; idx++)
        {
            list.Add(new SelectListItem
                         {
                             Value = idx.ToString(),
                             Text = idx.ToString(),
                             Selected = selected != null && selected.Contains(idx.ToString())
                         });
        }

        return list;
    }

View

@Html.CheckBoxFor(m => m.IncludeGuestsArrivedInTimeframe)
@Html.LabelFor(m => m.IncludeGuestsArrivedInTimeframe)
@Html.ListBoxFor(m => m.IncludeGuestsArrivedInTimeframeMonths, Model.TimeframeMonths)
@*@Html.ListBoxFor(m => m.IncludeGuestsArrivedInTimeframeYears, Model.TimeframeYears)*@
@Html.ListBox("IncludeGuestsArrivedInTimeframeYears", Model.TimeframeYears)

Best Solution

You need to set Selected property of SelectItemList class to true for the options which you want to be pre-selected.

Example:

@{
    var foo = new List<SelectListItem> { 
        new SelectListItem { Text = "Foo 1", Value = "1", Selected = true },
        new SelectListItem { Text = "Foo 2", Value = "2" },
        new SelectListItem { Text = "Foo 3", Value = "3", Selected = true }
    };
}

@Html.ListBox("foo", foo)

In this case, Foo 1 and Foo 3 should appear as pre-selected. The above code generates the below html markup:

<select id="foo" multiple="multiple" name="foo">
    <option selected="selected" value="1">Foo 1</option>
    <option value="2">Foo 2</option>
    <option selected="selected" value="3">Foo 3</option>
</select>

Edit:

First of all, replace this code:

list.Add(new SelectListItem {
     Value = idx.ToString(),
     Text = idx.ToString(),
     Selected = selected != null && selected.Contains(idx.ToString())
});

with this code:

list.Add(new SelectListItem {
     Value = idx.ToString(),
     Text = idx.ToString(),
     Selected = true
});

Then run the app. If all the options are pre-selected, then I bet that this selected != null && selected.Contains(idx.ToString()) does not satisfy the condition.