1

在 ASP.NET MVC (Razor) 项目中,我在编辑视图中使用带有多选选项的 ListBox,在使用 in 突出显示先前选择的项目时出现问题selectedValuesMultiSelectList所以我之前问了一个关于 SO的问题。根据对该问题给出的答案,我决定使用 ViewModel(带有 AutoMapper)将数据传递给视图,而不使用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);
    }

看法

<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:

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

楷模

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

看法

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

有什么区别……??

4

2 回答 2

1

问题在于您的构造MultiSelectList

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

您正在指定元素的值将从每个标记的Id属性中获取,但是对于实际选择的值,您将传递一个字符串数组,该数组可能对应于Name标记的 s。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- 以前的版本是选择标签,而不是 ids(当然他们比较不相等,苹果和橙子)。

于 2012-06-22T07:46:37.210 回答
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());
    }
于 2012-11-26T15:00:57.420 回答