MultiSelectList不会突出显示selectedValues列表中的项目

问题描述:

在ASP.NET MVC(Razor)项目中,我在编辑视图中使用带有多选择选项的ListBox,但在使用之前选中的项目时突出显示问题selectedValues in MultiSelectList,所以我问了一个question on SO以前。根据针对该问题给出的答案,我决定使用ViewModel(使用AutoMapper)将数据传递到视图,而不使用ViewBag,但仍然有同样的问题。它不会选择selectedValues中给出的项目名单MultiSelectList不会突出显示selectedValues列表中的项目

这是我的新代码

模型

public class Post 
{ 
    public int Id { get; set; } 
    ... 
    public string Tags { get; set; } 

} 

public class PostEditViewModel 
{ 
    private DocLibraryContext db = new DocLibraryContext(); 

    public int Id { get; set; } 
    .. 
    public MultiSelectList TagsList { get; set; } 

} 

控制器

public ActionResult Edit(int id) 
    { 

     Post post = db.Posts.Find(id); 
     PostEditViewModel postEditViewModel = Mapper.Map<Post, PostEditViewModel>(post); 

     var tagsQuery = from d in db.Tags 
         orderby d.Name 
         select d; 
     postEditViewModel.TagsList = new MultiSelectList(tagsQuery, "Id", "Name", post.Tags.Split(',')); 

     return View(postEditViewModel); 
    } 

VIEW

<div class="editor-field"> 
    @Html.ListBoxFor(model => model.Tags, Model.TagsList as MultiSelectList) 
</div> 

我在做什么错在这里?请帮助....


更新1:

改变控制器

public ActionResult Edit(int id) 
    { 

     Post post = db.Posts.Find(id); 
     PostEditViewModel postEditViewModel = Mapper.Map<Post, PostEditViewModel>(post); 

     var tagsQuery = from d in db.Tags 
         orderby d.Name 
         select d; 

     var selectedIds = post.Tags.Split(',').Select(n => tagsQuery.First(t => t.Name == n)); 
     postEditViewModel.TagsList = new MultiSelectList(tagsQuery, "Id", "Name", selectedIds); 

     return View(postEditViewModel); 
    } 

,但我得到了相同的结果。


更新2:

我试图改变代码(如this教程),它的工作,但我需要用以前的方法..

模型

public Post Post { get; set; } 
    public MultiSelectList TagsList { get; set; } 

    public PostEditViewModel(Post post) 
    { 
     Post = post; 
     var tagsQuery = from d in db.Tags 
         orderby d.Name 
         select d; 
     TagsList = new MultiSelectList(tagsQuery, "Name", "Name", post.Tags.Split(',')); 
    } 

控制器

public ActionResult Edit(int id) 
    { 

     Post post = db.Posts.Find(id); 
     return View(new PostEditViewModel(post)); 
    } 

VIEW

<div class="editor-field"> 
    @Html.ListBox("Tags", Model.TagsList as MultiSelectList) 
</div> 

做什么区别...?

问题是与你的MultiSelectList建设:

new MultiSelectList(tagsQuery, "Id", "Name", post.Tags.Split(',')); 

您指定的元素中的值将每个标签的Id财产所应采取,但后来的实际选择的值,你传递一个字符串数组,大概对应于标签的Name。不要紧,你也指定Name是显示文本将被确定的属性; selectedValues参数与值匹配,不显示文本。

为了解决这个问题,项目中的每个标签名到其对应的Id

var selectedIds = post.Tags.Split(',').Select(n => tagsQuery.First(t => t.Name == n).Id); 
new MultiSelectList(tagsQuery, "Id", "Name", selectedIds); 

更新:

糟糕,在上面的代码错误。

我编辑了答案,在selectedIds初始化结束时添加了一个必需的.Id - 之前的版本是选择标签,而不是id(当然他们正在比较不等,苹果和橘子)。

+0

对不起,它不工作的方式... :( – Nalaka526

+0

@ Nalaka526:邮政确切代码没有作为问题的更新 – Jon

+0

更新了问题 – Nalaka526

我有同样的问题,我用我自己的方法extention生成HTML和问题解决

public static MvcHtmlString ListBoxMultiSelectFor<TModel, TProperty>(
     this HtmlHelper<TModel> helper, 
     Expression<Func<TModel, TProperty>> expression, 
     IEnumerable<SelectListItem> selectList, 
     object htmlAttributes) 
    { 
     return ListBoxMultiSelectFor(helper, expression, selectList, new RouteValueDictionary(htmlAttributes)); 
    } 

    public static MvcHtmlString ListBoxMultiSelectFor<TModel, TProperty>(
     this HtmlHelper<TModel> helper, 
     Expression<Func<TModel, TProperty>> expression, 
     IEnumerable<SelectListItem> selectList, 
     IDictionary<string, object> htmlAttributes) 
    { 
     string name = ExpressionHelper.GetExpressionText(expression); 

     TagBuilder selectTag = new TagBuilder("select"); 
     selectTag.MergeAttributes(htmlAttributes); 
     selectTag.MergeAttribute("id", name, true); 
     selectTag.MergeAttribute("name", name, true); 
     foreach (SelectListItem item in selectList) 
     { 
      TagBuilder optionTag = new TagBuilder("option"); 
      optionTag.MergeAttribute("value", item.Value); 
      if (item.Selected) optionTag.MergeAttribute("selected", "selected"); 
      optionTag.InnerHtml = item.Text; 
      selectTag.InnerHtml += optionTag.ToString(); 
     } 

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