Existe-t-il un modèle pour lier une liste d'éléments à la vue. Il me semble avoir des problèmes avec le HttpPost. Je sais que Phil Haack a écrit un article de Nice mais il est daté et il a dit qu'ils pourraient avoir un correctif avec MVC 4.
Voici comment je le fais si j'ai besoin d'un formulaire affiché pour chaque élément et d'entrées pour diverses propriétés. Cela dépend vraiment de ce que j'essaie de faire.
ViewModel ressemble à ceci:
public class MyViewModel
{
public List<Person> Persons{get;set;}
}
Voir (avec BeginForm bien sûr):
@model MyViewModel
@for( int i = 0; i < Model.Persons.Count(); ++i)
{
@Html.HiddenFor(m => m.Persons[i].PersonId)
@Html.EditorFor(m => m.Persons[i].FirstName)
@Html.EditorFor(m => m.Persons[i].LastName)
}
Action:
[HttpPost]public ViewResult(MyViewModel vm)
{
...
Notez que lors de la publication, seules les propriétés qui avaient des entrées disponibles auront des valeurs. C'est-à-dire que si Person avait une propriété .SSN, elle ne serait pas disponible dans l'action de publication car ce n'était pas un champ du formulaire.
Notez que la façon dont la liaison de modèle de MVC fonctionne, il ne recherchera que des ID consécutifs. Donc, faire quelque chose comme ça où vous masquez conditionnellement un élément l'empêchera de lier toutes les données après le 5ème élément, car une fois qu'il rencontrera un écart dans les ID, il cessera de se lier. Même s'il y avait 10 personnes, vous n'obtiendrez que les 4 premiers sur le postback:
@for( int i = 0; i < Model.Persons.Count(); ++i)
{
if(i != 4)//conditionally hide 5th item,
{ //but BUG occurs on postback, all items after 5th will not be bound to the the list
@Html.HiddenFor(m => m.Persons[i].PersonId)
@Html.EditorFor(m => m.Persons[i].FirstName)
@Html.EditorFor(m => m.Persons[i].LastName)
}
}
Une solution propre pourrait être de créer une classe générique pour gérer la liste, vous n'avez donc pas besoin de créer une classe différente chaque fois que vous en avez besoin.
public class ListModel<T>
{
public List<T> Items { get; set; }
public ListModel(List<T> list) {
Items = list;
}
}
et lorsque vous retournez la vue, il vous suffit de faire simplement:
List<customClass> ListOfCustomClass = new List<customClass>();
//Do as needed...
return View(new ListModel<customClass>(ListOfCustomClass));
puis définissez la liste dans le modèle:
@model ListModel<customClass>
et prêt à partir:
@foreach(var element in Model.Items) {
//do as needed...
}
~ Contrôleur
namespace ListBindingTest.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
List<String> tmp = new List<String>();
tmp.Add("one");
tmp.Add("two");
tmp.Add("Three");
return View(tmp);
}
[HttpPost]
public ActionResult Send(IList<String> input)
{
return View(input);
}
}
}
~ Affichage de l'index fortement tapé
@model IList<String>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
@using(Html.BeginForm("Send", "Home", "POST"))
{
@Html.EditorFor(x => x)
<br />
<input type="submit" value="Send" />
}
</div>
</body>
</html>
~ Vue d'envoi fortement typée
@model IList<String>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Send</title>
</head>
<body>
<div>
@foreach(var element in @Model)
{
@element
<br />
}
</div>
</body>
</html>
C'est tout ce que vous aviez à faire homme, changer son modèle MyViewModel en IList.