2012-07-27 25 views
5

He encontrado otros temas al respecto, pero ninguno de ellos me hizo entender lo que estoy tratando de resolver.MVC 3: HTML.DisplayFor y la expresión Lambda

Estoy estudiando MVC 3 y tengo problemas con las expresiones Lambda que van con @ HTML.DisplayFor() en la plantilla de andamios.

estoy trabajando con la aplicación de ejemplo MvcMusicStore, la vista creada por el andamiaje se ve así:

@model IEnumerable<MvcMusicStore.Models.Album> 

... 

@foreach (var item in Model) { 
    <tr> 
     <td> 
      @Html.DisplayFor(modelItem => item.Genre.Name) 
     </td> 

entiendo que DisplayFor es un método de extensión a HTML y que se necesita una expresión como un parámetro. Investigué las expresiones de Lambda y las entiendo en otros contextos, como con cadenas enumerables. Por ejemplo:

cities.Where(s => s.StartsWith("L")); 

Lo que perturba mi mente es, que en el segundo ejemplo, la primera parte de la expresión (s) se utiliza realmente en la segunda parte (s.startswith ..), así que tiene sentido y entiendo lo que el programa está haciendo con eso. Pero este no es el caso en la vista MVC 3. modelItem no se usa en ningún lado. He intentado cambiar el nombre sólo "ModelItem" a lo que de este modo:

@Html.DisplayFor(iAmWearingShortPantsToday => item.Genre.Name) 

Este código funciona igual de bien, mostrando todos los elementos y valores correctamente. Esto me hace dudar de que en este caso "modelItem" se use realmente para cualquier cosa. Pero entonces, ¿por qué está allí?

También he tratado de traducir esta expresión Lambda en un delegado (que creo que es la forma corta de), así:

@(Html.DisplayFor(delegate(IEnumerable<MvcMusicStore.Models.Album> modelItem) { return item.Genre.Name; })) 

Esto, sin embargo, no funciona. El error resultante es:

CS1946: Una expresión método anónimo no se puede convertir a un árbol de expresión

De ahí mi pregunta:

¿Qué es "ModelItem" bueno para? ¿Qué hace HTML.DisplayFor() con modelItem? ¿Hay otros casos tal vez, donde esta primera parte de la expresión se vuelve significativa?

Si es posible traducir esta expresión en un delegado adecuado, eso también podría ayudarme a entender qué está sucediendo exactamente.

Muchas gracias

+0

mint -buena pregunta +1 –

Respuesta

2

Entiendo su confusión. En realidad, la variable modelItem nunca se usa en la expresión lambda. Lo que se usa es la variable item que se captura en un cierre desde el contexto externo. La variable item es simplemente la variable local definida en el ciclo foreach.

Por cierto, cuando ve una expresión como modelItem => item.Genre.Name en la vista ASP.NET MVC, eso suele ser señal de una mala práctica de codificación. Evítalo. Internet está lleno de malos ejemplos. De Verdad. Estoy harto de ver esto. Por favor, ayúdame a erradicar esta práctica.

Aquí es un método alternativo en el que se utiliza realmente la variable:

@model IList<MvcMusicStore.Models.Album> 
... 

@for (var i = 0; i < Model.Count; i++) { 
    <tr> 
     <td> 
      @Html.DisplayFor(x => x[i].Genre.Name) 
     </td> 
     ... 
    </tr> 
} 

Y aún mejor. ¿Por qué escribir loops? Cuando podemos utilizar directamente plantillas editor/visualización:

@model IEnumerable<MvcMusicStore.Models.Album> 
... 
@Html.DisplayForModel() 

y luego definir una plantilla de visualización que automáticamente se rindió por ASP.NET MVC para cada elemento de la colección modelo (~/Views/Shared/DisplayTemplates/Album.cshtml)

@model Album 
<tr> 
    <td> 
     @Html.DisplayFor(x => x.Genre.Name) 
    </td> 
    ... 
</tr> 
+0

¿Alguna razón particular por la que usaste un 'for' en lugar de un bucle' foreach'? –

+0

Sí, la razón particular es que hay millones de preguntas en StackOverflow usando 'foreach' y campos de entrada dentro, como' @ Html.TextBoxFor (modelItem => item.Name) 'y preguntando por qué no se obtiene la acción POST cualquier valor de vuelta. Por qué el modelo siempre es nulo. ¿Sabes por qué? –

+0

1: dices modelItem => item.Genre.Name es una mala práctica. Pero esto es exactamente lo que sale del andamio MVC 3 predeterminado. ¿Cómo puede ser esta una mala práctica? También está en el libro que estoy leyendo, Professional MVC 3 de Wrox. 2: Entonces, si no se usa modelItem, ¿por qué está allí? ¿Tienes una teoría? –

0

No estoy seguro de poder responder a su pregunta, pero la parte correcta se usa para indicar DisplayFor para qué propiedad creará una pantalla. Se usa para determinar el tipo de propiedad (utilizada para seleccionar cómo mostrar el valor) y el valor.

Si se utiliza en un TextBoxFor, también se utiliza para recuperar el nombre de la propiedad, por lo que el cuadro de texto puede obtener el nombre correcto.

Creo que la expresión en muchos de los métodos de extensión html-helper es en realidad un poco extraña, pero es la manera fácil de dejar que el código obtenga toda esta información, sin tener que escribirla como parámetros de cadena (eso fallaría si cambiaras algo, sin dar un error en tiempo de compilación).

Cuestiones relacionadas