Why is ListBoxFor not selecting items, but ListBox

2019-01-22 02:13发布

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.

7条回答
The star\"
2楼-- · 2019-01-22 03:05

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 the selectedItems against the listitems but no, that's not how it works. Despite the fact that MultiListItem 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 the SelectItemList.

So, implement IConvertible, return the string value from ToString which would match the value in the SelectItemList. e.g in my case CountryCode was serialized into the SelectItem Value property , so in ToString IConvertible I returned CountryCode. Now it all selects correctly.

I will point out the TypeConverter is used on the way in. This time its the inverse. That Countrycode comes back in and "EN" needs converting into Country class instance. That's where the TypeConverter 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 implement IConvertible. If its from the entity framework as my company is then you'll need to use the partial class to implement IConvertible and implement ToString and decorate it with a TypeConverter you wrote too.

查看更多
登录 后发表回答