I have the following code in my view:
<%= Html.ListBoxFor(c => c.Project.Categories,
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
<%= Html.ListBox("MultiSelectList",
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
The only difference is that the first helper is strongly typed (ListBoxFor), and it fails to show the selected items (1,2), even though the items appear in the list, etc. The simpler ListBox is working as expected.
I'm obviously missing something here. I can use the second approach, but this is really bugging me and I'd like to figure it out.
For reference, my model is:
public class ProjectEditModel
{
public Project Project { get; set; }
public IEnumerable<Project> Projects { get; set; }
public IEnumerable<Client> Clients { get; set; }
public IEnumerable<Category> Categories { get; set; }
public IEnumerable<Tag> Tags { get; set; }
public ProjectSlide SelectedSlide { get; set; }
}
Update
I just changed the ListBox name to Project.Categories (matching my model) and it now FAILS to select the item.
<%= Html.ListBox("Project.Categories",
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
I'm obviously not understanding the magic that is happening here.
Update 2
Ok, this is purely naming, for example, this works...
<%= Html.ListBox("Project_Tags",
new MultiSelectList(Model.Tags, "Id", "Name", Model.Project.Tags.Select(t => t.Id)))%>
...because the field name is Project_Tags, not Project.Tags, in fact, anything other than Tags or Project.Tags will work. I don't get why this would cause a problem (other than that it matches the entity name), and I'm not good enough at this to be able to dig in and find out.
The correct answer is that it doesn't work very well. As such I read the MVC code. What you need to do is implement IConvertible and also create a TypeConverter.
So, in my instance I had a
Country
class, such that people could choose from a list of countries. No joy in selecting it. I was expecting an object equals comparison on theselectedItems
against thelistitems
but no, that's not how it works. Despite the fact thatMultiListItem
works and correctly gets the selected items, the moment it is bound to your model it's all based on checking that the string represnetation of your object instance matches the string"value"
(or name if that is missing) in the list of items in theSelectItemList
.So, implement
IConvertible
, return the string value fromToString
which would match the value in theSelectItemList
. e.g in my caseCountryCode
was serialized into theSelectItem
Value
property , so inToString IConvertible
I returnedCountryCode
. Now it all selects correctly.I will point out the
TypeConverter
is used on the way in. This time its the inverse. ThatCountrycode
comes back in and "EN" needs converting intoCountry
class instance. That's where theTypeConverter
came in. It's also about the time I realised how difficult this approach is to use.p.s so on your
Category
class you need to implementIConvertible
. If its from the entity framework as my company is then you'll need to use the partial class to implementIConvertible
and implementToString
and decorate it with aTypeConverter
you wrote too.