在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));
}
有什么不同...... ??
答案 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());
}