I have a many to many relationship between cars and many other tables. In my view I want to be able to have a multiselect list for items such as lights. I've tried many different formats I can't seem to get the list to set selected items.My preferred way to do it would be @Html.ListBoxFor(model => model.enitity.relatedentity, Model.SomeSelectListItemList) , but I can not seem to get list to set selected items in the view.
我和汽车之间有许多关系。在我看来,我希望能够为灯光等项目提供多选列表。我尝试了很多不同的格式,我似乎无法获得列表来设置所选项目。我喜欢的方法是@Html.ListBoxFor(model => model.enitity.relatedentity,Model.SomeSelectListItemList),但是我似乎无法获取列表以在视图中设置所选项目。
Below is my code I was testing with I use Asp.net MVC5, C# and entity framework 6.
下面是我测试的代码,我使用的是Asp.net MVC5,C#和实体框架6。
This is my controller action
这是我的控制器动作
// GET: Car/Edit/
[Authorize(Roles = "Ecar")]
public ActionResult Edit(int id)
{
CarsEditViewModel carEditViewModel = new CarsEditViewModel();
carEditViewModel.Cars = unitOfWorkcar.CarRepository.FindIncluding(id);
IList<Approval> approvalList = unitOfWorkcar.ApprovalRepository.All.ToList();
IList<Connector> connectorList = unitOfWorkcar.ConnectorRepository.All.ToList();
IList<InputVoltage> inputVoltagesList = unitOfWorkcar.InputVoltageRepository.All.ToList();
carEditViewModel.ApprovalList = from c in approvalList select new SelectListItem { Text = c.Name, Value = c.Id.ToString(), Selected = true};
carEditViewModel.Categories = new MultiSelectList(carEditViewModel.ApprovalList, "Value", "Text", "Selected");
// ,carEditViewModel.ApprovalList.Select(c => c.Text),carEditViewModel.ApprovalList.Select(c => c.Selected)
//carEditViewModel.ApprovalList = from c in approvalList select new MultiSelectList( //{ Selected = (carEditViewModel.Cars.Approvals.Any(app => app.Id == c.Id)) , Text = c.Name, Value = c.Id.ToString() };
// carEditViewModel.ConnectorList = from c in connectorList select new SelectListItem { Selected = true, Text = c.Name, Value = c.Id.ToString() };
carEditViewModel.InputVoltageList = from c in inputVoltagesList select new SelectListItem { Text = c.Name, Value = c.Id.ToString() };
return View(carEditViewModel);
}
Here is my view
这是我的看法
@model NewBobPortal.ViewModels.CarsEditViewModel
@using (Html.BeginForm())
{
@* @Html.ListBoxFor("SelectedApprovals",model => model., new { @class = "multiselect" })*@
@*@Html.ListBoxFor(model => model.Cars.Approvals, Model.ApprovalList)
@Html.ListBoxFor(model => model.Cars.Connectors,Model.ConnectorList, new {Multiple = "multiple"})
@Html.ListBoxFor(model => model.ConnectorList, Model.ConnectorList)*@
@*@Html.ListBox("test",Model.Cars.InputVoltages, Model.InputVoltageList)*@
@Html.DropDownList("somethingelse", new MultiSelectList(Model.InputVoltageList, "Value", "Text", Model.InputVoltageList.Select(c => c.Value)), new { multiple = "multiple" })
@Html.DropDownListFor(model => model.Cars.InputVoltages , new MultiSelectList(Model.LensColorList, "Value", "Text", Model.LensColorList.Select(c => c.Value)), new { multiple = "multiple" })
@Html.ListBoxFor(m => m.Cars.Approvals, Model.Categories)
<p>
<input type="submit" value="Save" />
</p>
}
}
This is my viewmodel
这是我的viewmodel
using NewBobPortal.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace NewBobPortal.ViewModels
{
public class CarsEditViewModel
{
public Car Cars { get; set; }
public IEnumerable<SelectListItem> ApprovalList { get; set; }
public IEnumerable<MultiSelectList> ConnectorList { get; set; }
public IEnumerable<SelectListItem> InputVoltageList { get; set; }
public MultiSelectList Categories { get; set; }
public IEnumerable<Approval> SelectedCategories { get; set; }
}
}
}
1 个解决方案
#1
9
The biggest problem with posting values for a many-to-many relationship is that there's no direct field to bind to on your model. This is where view models become very handy, which you're already using, but not quite in the right way for this.
发布多对多关系的值的最大问题是在模型上没有要绑定的直接字段。这是视图模型变得非常方便的地方,您已经在使用它,但不是以正确的方式。
First you need your SelectList
, which can actually just be an IEnumerable<SelectListItem>
. This will contain all available options, which is easy enough. So in your view model:
首先你需要你的SelectList,它实际上只是一个IEnumerable
public IEnumerable<SelectListItem> CategoryChoices { get; set; }
And in your action:
在你的行动中:
carEditViewModel.CategoryChoices = approvalList.Select(m => new SelectListItem {
Text = c.Name,
Value = c.Id.ToString()
});
Notice that I'm not setting Selected
: we'll let the HtmlHelper handle that. I'm also not dealing with a MultiSelectList
yet either.
请注意,我没有设置Selected:我们将让HtmlHelper处理它。我也没有处理MultiSelectList。
Now, you'll also need something to post back to, since your values will be ids, we'll use a List<int>
, so in your view model:
现在,您还需要回复一些内容,因为您的值将是id,我们将使用List
private List<int> selectedCategories;
public List<int> SelectedCategories
{
get
{
if (selectCategories == null)
{
selectedCategories = Categories.Select(m => m.Id).ToList();
}
return selectedCategories;
}
set { selectedCategories = value; }
}
There's a bit going on here. The set
method of the property is simple: when we get a posted value back, just set selectedCategories
to that. The get
is a bit more complicated: here we need to condense down your list of category objects (called Categories
here because I don't know where this is actually coming from) into a simple list of ids for those categories.
这里有一点点。属性的set方法很简单:当我们返回一个已发布的值时,只需将selectedCategories设置为该值即可。 get有点复杂:在这里我们需要压缩你的类别对象列表(这里称为Categories,因为我不知道它实际来自哪里)到这些类别的id的简单列表中。
Now, in your view:
现在,在您看来:
@Html.ListBoxFor(m => m.SelectedCategories, Model.CategoryChoices)
That's all you need. You're using a ListBox
control so it's already a multiple select list. And, by binding it to the list of all currently selected ids, it knows which items to select automatically in the list of SelectListItem
s it gets from Model.CategoryChoices
.
这就是你所需要的一切。您正在使用ListBox控件,因此它已经是一个多选列表。并且,通过将其绑定到所有当前选定的ID的列表,它知道从Model.CategoryChoices获取的SelectListItem列表中自动选择哪些项目。
In your post action, you then need to translate these ids into their associated objects:
在您的帖子操作中,您需要将这些ID转换为其关联对象:
var newCategories = repository.Categories.Where(m => carEditViewModel.SelectedCategories.Contains(m.Id));
Then, you can set your model's categories to this new list manually:
然后,您可以手动将模型的类别设置为此新列表:
car.Categories = newCategories;
#1
9
The biggest problem with posting values for a many-to-many relationship is that there's no direct field to bind to on your model. This is where view models become very handy, which you're already using, but not quite in the right way for this.
发布多对多关系的值的最大问题是在模型上没有要绑定的直接字段。这是视图模型变得非常方便的地方,您已经在使用它,但不是以正确的方式。
First you need your SelectList
, which can actually just be an IEnumerable<SelectListItem>
. This will contain all available options, which is easy enough. So in your view model:
首先你需要你的SelectList,它实际上只是一个IEnumerable
public IEnumerable<SelectListItem> CategoryChoices { get; set; }
And in your action:
在你的行动中:
carEditViewModel.CategoryChoices = approvalList.Select(m => new SelectListItem {
Text = c.Name,
Value = c.Id.ToString()
});
Notice that I'm not setting Selected
: we'll let the HtmlHelper handle that. I'm also not dealing with a MultiSelectList
yet either.
请注意,我没有设置Selected:我们将让HtmlHelper处理它。我也没有处理MultiSelectList。
Now, you'll also need something to post back to, since your values will be ids, we'll use a List<int>
, so in your view model:
现在,您还需要回复一些内容,因为您的值将是id,我们将使用List
private List<int> selectedCategories;
public List<int> SelectedCategories
{
get
{
if (selectCategories == null)
{
selectedCategories = Categories.Select(m => m.Id).ToList();
}
return selectedCategories;
}
set { selectedCategories = value; }
}
There's a bit going on here. The set
method of the property is simple: when we get a posted value back, just set selectedCategories
to that. The get
is a bit more complicated: here we need to condense down your list of category objects (called Categories
here because I don't know where this is actually coming from) into a simple list of ids for those categories.
这里有一点点。属性的set方法很简单:当我们返回一个已发布的值时,只需将selectedCategories设置为该值即可。 get有点复杂:在这里我们需要压缩你的类别对象列表(这里称为Categories,因为我不知道它实际来自哪里)到这些类别的id的简单列表中。
Now, in your view:
现在,在您看来:
@Html.ListBoxFor(m => m.SelectedCategories, Model.CategoryChoices)
That's all you need. You're using a ListBox
control so it's already a multiple select list. And, by binding it to the list of all currently selected ids, it knows which items to select automatically in the list of SelectListItem
s it gets from Model.CategoryChoices
.
这就是你所需要的一切。您正在使用ListBox控件,因此它已经是一个多选列表。并且,通过将其绑定到所有当前选定的ID的列表,它知道从Model.CategoryChoices获取的SelectListItem列表中自动选择哪些项目。
In your post action, you then need to translate these ids into their associated objects:
在您的帖子操作中,您需要将这些ID转换为其关联对象:
var newCategories = repository.Categories.Where(m => carEditViewModel.SelectedCategories.Contains(m.Id));
Then, you can set your model's categories to this new list manually:
然后,您可以手动将模型的类别设置为此新列表:
car.Categories = newCategories;