2012-06-11 7 views
5

Data una classeselezionare le voci dagli Lista <T> in MVC 4 utilizzando Modello Binding

public class Person 
{ 
    // Some general properties 

    public List<Hobby> Hobbies { get; set; } 
} 

public class Hobby 
{ 
    // Some properties e.g. Name, etc. 
} 

static List<Hobby> AllHobbies { get; } 

E 'possibile creare una vista che permette all'utente di selezionare i suoi hobby utilizzando vincolante modello?

Sarebbe certamente possibile visualizzare in loop AllHobbies e rendere uno <input type="checkbox" /> per ciascuno, quindi collegare i valori selezionati manualmente nel controller di postback. Sembra che questo dovrebbe essere fattibile con il modello di rilegatura, ma non vedo come.

risposta

11

Certo, ti consiglierei di utilizzare i modelli di editor.

Supponiamo che un hobby ha un nome e un campo booleano che indica se è stato selezionato dall'utente:

public class Hobby 
{ 
    public string Name { get; set; } 
    public bool Selected { get; set; } 
} 

poi un controller per alimentare il modello nella vista ed elaborare la presentazione sotto forma:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     var person = new Person 
     { 
      Hobbies = new[] 
      { 
       new Hobby { Name = "hobby 1" }, 
       new Hobby { Name = "hobby 2", Selected = true }, 
       new Hobby { Name = "hobby 3" }, 
      }.ToList() 
     }; 
     return View(person); 
    } 

    [HttpPost] 
    public ActionResult Index(Person person) 
    { 
     var selectedHobbies = person 
      .Hobbies 
      .Where(x => x.Selected).Select(x => x.Name); 
     string message = string.Join(",", selectedHobbies); 
     return Content("Thank you for selecting: " + message); 
    } 
} 

poi una vista contenente il modulo che permette all'utente di selezionare hobby:

@model Person 

@using (Html.BeginForm()) 
{ 
    <h2>Hobbies</h2> 
    @Html.EditorFor(x => x.Hobbies) 
    <button type="submit">OK</button> 
} 

e un editor di modelli corrispondente che verrà automaticamente eseguito il rendering per ogni elemento della collezione Hobbies (~/Views/Home/EditorTemplates/Hobby.cshtml -> Si noti che il nome e la posizione del modello è importante):

@model Hobby 

<div> 
    @Html.LabelFor(x => x.Selected, Model.Name) 
    @Html.HiddenFor(x => x.Name) 
    @Html.CheckBoxFor(x => x.Selected) 
</div> 

Per scenari di editing più avanzate lo farei ti consigliamo di consultare lo blog post di Steven Sanderson su questo argomento.

+0

+1, ottime informazioni. La classe 'Hobby' tuttavia non ha (e non dovrebbe) avere un booleano che indica se un particolare utente lo ha selezionato dal punto di vista del modello di dominio (questo è ovviamente un esempio semplificato). Devo aggiungere un campo booleano temporaneo all'oggetto per supportarlo oppure esiste un altro modo per eseguire il bind senza questo campo aggiuntivo? –

+4

No, il tuo errore è che stai passando un modello di dominio alla tua vista. Questo è sbagliato. È necessario definire un modello di vista. All'interno di questo modello di vista si avrà una proprietà booleana "Selected" che ti permetterà di lavorare con le caselle di controllo all'interno della vista e recuperare i valori selezionati dall'utente. Quindi mapperai il risultato sul tuo modello di dominio per fare tutto ciò che devi fare con esso. Ricorda la regola più importante in MVC: le azioni del controller passano/prendono solo i modelli di vista da/per le viste. Non modelli di dominio. I modelli di vista sono classi progettate specificamente per soddisfare i requisiti della vista data. –

+0

Potete consigliare un modello per una mappatura efficiente tra il modello di dominio e il modello di visualizzazione (come nel caso di codifica e test di tempo trascorso)? Questa è in realtà la prima istanza (anche se faccio molto poco sviluppo dell'interfaccia utente) dove c'è stata qualche differenza tra i due. –

Problemi correlati