Не полагайтесь слишком сильно на леса. Все дело в том, что он дает вам базу для работы; это не все, что вам нужно. Вы можете и должны модифицировать строительные леса в соответствии с вашими потребностями, и, честно говоря, чаще всего легче начинать с нуля, чем пытаться отменить все ненужные пушистые добавления.
Сказанное, особенно при выборе нескольких связанных предметов сразу, вы необходимо модель. Попытка использовать вашу сущность для этого быстро выйдет из строя. Так создать класс, как:
public class GroupViewModel
{
// `Group` properties you need to edit here
public List<int> SelectedSubscriberIds { get; set; }
public IEnumerable<SelectListItem> SubscriberChoices { get; set; }
}
Затем в контроллере:
// We'll use this code multiple times so it's factored out into it's own method
private void PopulateSubscriberChoices(GroupViewModel model)
{
model.SubscriberChoices = db.Subscribers.Select(m => new SelectListItem
{
Value = m.Id.ToString(),
Text = m.FirstName + " " + m.LastName
});
}
public ActionResult Create()
{
var model = new GroupViewModel();
PopulateSubscriberChoices(model);
return View(model);
}
[HttpPost]
public ActionResult Create(GroupViewModel model)
{
if (ModelState.IsValid)
{
// Map the posted values onto a new `Group` instance. To set `Subscribers`,
// lookup instances from the database using the list of ids the user chose
var group = new Group
{
Name = model.Name,
Subscribers = db.Subscribers.Where(m => model.SelectedSubscriberIds.Contains(m.Id))
};
db.Groups.Add(group);
db.SaveChanges()
return RedirectToAction("Index");
}
PopulateSubscriberChoices(model);
return View(model);
}
public ActionResult Edit(int id)
{
var group = db.Groups.Find(id);
if (group == null)
{
return new HttpNotFoundResult();
}
// Map `Group` properties to your view model
var model = new GroupViewModel
{
Name = group.Name,
SelectedSubscriberIds = group.Subscribers.Select(m => m.Id).ToList()
};
PopulateSubscriberChoices(model);
return View(model);
}
[HttpPost]
public ActionResult Edit(int id, GroupViewModel model)
{
var group = db.Groups.Find(id);
if (group == null)
{
return new HttpNotFoundResult();
}
if (ModelState.IsValid)
{
group.Name = model.Name;
// Little bit trickier here
// First remove subscribers that are no longer selected
group.Subscribers.Where(m => !model.SelectedSubscriberIds.Contains(m.Id))
.ToList().ForEach(m => group.Subscribers.Remove(m));
// Now add newly selected subscribers
var existingSubscriberIds = group.Subscribers.Select(m => m.Id);
var newSubscriberIds = model.SelectedSubscriberIds.Except(existingSubscriberIds);
db.Subscribers.Where(m => newSubscriberIds.Contains(m.Id))
.ToList().ForEach(m => group.Subscribers.Add(m));
db.Entry(group).State = EntityState.Modified;
db.SaveChanges()
return RedirectToAction("Index");
}
PopulateSubscriberChoices(model);
return View(model);
}
Редактирование после действия является самым трудным. Чтобы не получить ошибок в дублирующих ключах и т. Д., Вам необходимо убедиться, что вы не добавляете в коллекцию дубликаты. Вам также необходимо убедиться, что вы удаляете связь между этой группой и любыми элементами, которые пользователь не выбрал. Кроме этого, это довольно прямолинейно.
Наконец, в ваших взглядах, вы просто нужно, чтобы сделать список выбора:
@model Namespace.To.GroupViewModel
...
@Html.ListBoxFor(m => m.SelectedSubscriberIds, Model.SubscriberChoices)
UPDATE
Добавление преобразованного кода VB. Это может не работать на 100%. Любой, кто имеет больше опыта работы с VB, может отредактировать это, чтобы исправить любые проблемы.
вид Модель
Public Class GroupViewModel
' Group properties you need to edit here
Public Property SelectedSubscriberIds As List(Of Integer)
Public Property SubscriberChoices As IEnumerable(Of SelectListItem)
End Class
Controller Код
' We'll use this code multiple times so it's factored out into it's own method
Private Sub PopulateSubscriberChoices(model As GroupViewModel)
model.SubscriberChoices = db.Subscribers.[Select](Function(m) New SelectListItem With { _
.Value = m.Id, _
.Text = m.FirstName & " " & m.LastName _
})
End Sub
Public Function Create() As ActionResult
Dim model as New GroupViewModel
PopulateSubscriberChoices(model)
Return View(model)
End Function
<HttpPost> _
Public Function Create(model As GroupViewModel) As ActionResult
If ModelState.IsValid Then
' Map the posted values onto a new `Group` instance. To set `Subscribers`,
' lookup instances from the database using the list of ids the user chose
Dim group = New Group With { _
.Name = model.Name, _
.Subscribers = db.Subscribers.Where(Function(m) model.SelectedSubscriberIds.Contains(m.Id)) _
}
db.Groups.Add(group)
db.SaveChanges()
Return RedirectToAction("Index")
End If
PopulateSubscriberChoices(model)
Return View(model)
End Function
Public Function Edit(id As Integer) As ActionResult
Dim group = db.Groups.Find(id)
If group Is Nothing Then
Return New HttpNotFoundResult()
End If
' Map `Group` properties to your view model
Dim model = New GroupViewModel With { _
.Name = group.Name, _
.SelectedSubscriberIds = group.Subscribers.[Select](Function(m) m.Id).ToList _
}
PopulateSubscriberChoices(model)
Return View(model)
End Function
<HttpPost> _
Public Function Edit(id As Integer, model As GroupViewModel) As ActionResult
Dim group = db.Groups.Find(id)
If group Is Nothing Then
Return New HttpNotFoundResult()
End If
If ModelState.IsValid Then
group.Name = model.Name
' Little bit trickier here
' First remove subscribers that are no longer selected
group.Subscribers.Where(Function(m) Not model.SelectedSubscriberIds.Contains(m.Id)).ToList().ForEach(Function(m) group.Subscribers.Remove(m))
' Now add newly selected subscribers
Dim existingSubscriberIds = group.Subscribers.[Select](Function(m) m.Id)
Dim newSubscriberIds = model.SelectedSubscriberIds.Except(existingSubscriberIds)
db.Subscribers.Where(Function(m) newSubscriberIds.Contains(m.Id)).ToList().ForEach(Function(m) group.Subscribers.Add(m))
db.Entry(group).State = EntityState.Modified
db.SaveChanges()
Return RedirectToAction("Index")
End If
PopulateSubscriberChoices(model)
Return View(model)
End Function
Спасибо за помощь ... Но придется преобразовать его в VB, чтобы проверить, работает ли он в моем коде или нет. Я не C# парень ... :( –
Извините, но я полностью пропустил часть VB, но я не парень VB, поэтому мой ответ не мог быть таким полным. Вы должны быть в состоянии получить больше в том, что там просто используется что-то вроде http://converter.telerik.com/ –
Добавлен конвертированный код VB. Он может не работать без изменений, но он подойдет вам хотя бы ближе. –