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

时间:2012-06-22 07:41:27

标签: asp.net-mvc-3 razor listbox viewmodel

在ASP.NET MVC(Razor)项目中,我在编辑视图中使用带有多选选项的列表框,在{{1}中使用selectedValues突出显示以前选择的项目时出现问题所以我之前问过question on SO。根据为该问题给出的答案,我决定使用ViewModel(使用AutoMapper)将数据传递给View,而不使用MultiSelectList,但我仍然遇到同样的问题..它没有选择项目在ViewBag列表

中给出

这是我的新代码

模型

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);
    }

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


更新1:

将控制器更改为

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

但我得到的结果相同。


更新2:

我尝试更改代码(如在this教程中),这有效,但我需要使用以前的方法..

模型

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);
    }

控制器

    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));
    }

有什么不同...... ??

2 个答案:

答案 0 :(得分:1)

问题在于构建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);

<强>更新

哎呀,上面的代码中有一个错误。

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

答案 1 :(得分:0)

我有同样的问题,我使用自己的扩展方法来生成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());
    }