2012-10-02 12 views
8

tengo la siguiente distribución de clases en MVC:MVC - Edición de una lista de objetos

public class ReportModel 
{ 
    List<SomeItem> items; 
    string value; 
    string anotherValue; 
} 

ahora creo una vista inflexible en MVC de este tipo y hacer que los campos de texto editables para editar cada valor, así como utilice un bucle foreach para rellenar campos de texto para editar los elementos en la lista de algún elemento.

cuando presento el método de httppost los valores singulares vuelven bien en el objeto de modelo de informe pero la lista no se devuelve en el objeto. ¿Cómo debe hacerse esto?

Cuando digo HttpPost Me refiero al método que MVC es la publicación de nuevo a

[HttpPost] 
public ActionResult EditReport(ReportModel report) 
{ 
    // Save the report in here after the update on the UI side 
} 

Ver código para publicar la lista de someitem

if (Model.items != null && Model.items.Count > 0) 
{ 
    for (int i = 0; i < Model.items.Count; i++) 
    {     
     <div class="editrow"> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyOne) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyOne) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyOne) 
       </div> 
      </div> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyTwo) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyTwo) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyTwo) 
       </div> 
      </div> 
      <div class="edititem"> 
       <div class="editor-label"> 
        @Html.LabelFor(m => m.items.ElementAt(i).propertyThree) 
       </div> 
       <div class="editor-field"> 
        @Html.TextBoxFor(m => m.items.ElementAt(i).propertyThree) 
        @Html.ValidationMessageFor(m => m.items.ElementAt(i).propertyThree) 
       </div> 
      </div> 
     </div> 
    } 
} 
+0

Primero: Nitpicking: En el título: lista, no se enciende. Segundo: ¿Cuál es el método de httppost del que está hablando? ¿Estamos hablando de Android aquí? Por favor, agrega esa etiqueta para denotarlo. – bldoron

+6

¿Has leído esto: http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx –

+0

@KirillBestemyanov Eso no es exactamente lo que estoy buscando, ya que espero volver a incluirlos en el modelo de informe no como parámetros separados para la función – DMCApps

Respuesta

1

referencia de Kirill a la entrada del blog de Scott Hanselman es correcto, pero lo estás leyendo demasiado estrechamente. En el ejemplo que se muestra, pasa la matriz al método de acción, pero también podría contenerse fácilmente dentro del modelo principal. El mismo concepto se aplica.

Sin embargo, una cosa a saber es que el archivador de modelo predeterminado no crea instancias de clases anidadas, por lo que no creará una instancia de la clase List, lo que significa que siempre será nula. Para solucionar esto, debe crear una instancia de la clase de lista vacía en el constructor.

Esto es solo una parte del problema, aunque los datos deben tener el formato correcto para que el encuadernador de modelos lo vincule. Aquí es donde aparece la publicación de blog de Scott, ya que proporciona el formato necesario para que la carpeta de modelos reconozca los datos como una lista.

Esto normalmente se maneja para usted si usa una Plantilla de Editor y usa Html.EditorFor (m => m.Items) y luego tiene una SomeTime.cshtml EditorTemplate. Esto trata de los problemas de la nomenclatura de los elementos de la colección (siempre que también uses ayudantes fuertemente tipados en la plantilla).

11

No use ElementAt(1) en sus expresiones lambda => esto arruina los nombres de sus campos de entrada. Por favor, lea la publicación del blog que Kirill le sugirió.

lo que podría utilizar acceso indexado:

for (int i = 0; i < Model.items.Count; i++) 
{     
    <div class="editrow"> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyOne) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyOne) 
       @Html.ValidationMessageFor(m => m.items[i].propertyOne) 
      </div> 
     </div> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyTwo) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyTwo) 
       @Html.ValidationMessageFor(m => m.items[i].propertyTwo) 
      </div> 
     </div> 
     <div class="edititem"> 
      <div class="editor-label"> 
       @Html.LabelFor(m => m.items[i].propertyThree) 
      </div> 
      <div class="editor-field"> 
       @Html.TextBoxFor(m => m.items[i].propertyThree) 
       @Html.ValidationMessageFor(m => m.items[i].propertyThree) 
      </div> 
     </div> 
    </div> 
} 

Por supuesto, con el fin de tener acceso a la colección indexador esto supone que su propiedad items se declara como sea List<SomeItem> o SomeItem[]. Si es un IEnumerable<SomeItem>, no funcionará. Simplemente cambie el tipo de esta propiedad en su modelo de vista.

+0

hmm Creo que el mío es un IEnumerable porque estoy usando un objeto entidad pasado directamente a la vista y creo que está esperando un IEnumerable. Básicamente tengo que crear un objeto modelview, esto es algo indeseable porque hay alrededor de 180 campos en mi objeto (no hay elección en reducirlo porque no es mi proyecto jajaja). – DMCApps

+2

Tiene 180 campos en su formulario y todos ellos son obligatorios por la vista? Si este es el caso, usar un modelo de vista no traerá muchos beneficios. Entonces, en este caso, podría usar una plantilla de editor personalizada. No escriba ningún bucle 'for' en la vista. Simplemente reemplace todo el ciclo con '@ Html.EditorFor (x => x.items)' y luego defina una plantilla de editor personalizada para la clase 'SomeItem' -' ~/Views/Shared/EditorTemplates/SomeItem.cshtml'. ASP.NET MVC invocará automáticamente esta plantilla personalizada para cada elemento de la colección de elementos, por lo que la plantilla se escribirá fuertemente en '@model SomeItem' –

+1

Luego, dentro de la plantilla personalizada, coloque el marcado con los divs y use las siguientes expresiones:' @ Html.TextBoxFor (x => x.propertyOne), ... '. En este caso, el ayudante generará nombres propios para los campos de entrada. –

Cuestiones relacionadas