none
Generar un formulario en una vista de manera dinamica... Es posible???? RRS feed

  • Pregunta

  • Buenas...(y muchas gracias de antemano)

    Me gustaria me echaran un cable a la hora de montar una vista en mvc. Depsues de haber leido algo, me ha quedado muy grabado el mal uso que se hace de este patron en el momento en el que ponemos "logica" dentro de una vista.. Es por ello, que me encuentro en la situación de generar un formulario de una manera más o menos dinamica, y aunque tengo alguna solucion en la cabeza, me gustaria haber si Uds. me pueden orientar.

    El tema es el siguiente

    Tengo varias clases (en este ejemplo pondre dos :) ) que implentan una interfaz comun.

    Public Interface IProductos
            Function GetImporte() As Decimal
    End Interface
    
    Public Class Producto1
            Implements IProductos
    
            Public Property ImporteMensual As Decimal
            Public Property Meses As Integer
            Public Function GetImporte() As Decimal Implements IProductos.GetImporte
                Return ImporteMensual * Meses
            End Function
    End Class
    
    Public Class Producto2
            Implements IProductos
    
            Public Property ImporteAnual As Decimal
            
            Public Function GetImporte() As Decimal Implements IProductos.GetImporte
                Return ImporteAnual
            End Function
    End Class

    Tambien, tengo un clase que implementa una lista de "productos". La idea es que dentro de esta lista, se añade cualquier producto que implemente la interfaz iProductos.

    Public Class Simulador
            Public Property Nombre As String
            Public Property Productos As List(Of IProductos)
    
            Public Sub New()
                Productos = New List(Of IProductos)
            End Sub
    End Class

    Ahora viene mi duda.En la accion del controlador, devuelvo el modelo que dependiendo de una serie de consultas la lista de productos puede variar...

    Function Index() As ActionResult Dim sim As New Simulador sc.Productos.Add(Producto1)
    // o sc.Productos.Add(Producto2)
    // o sc.Productos.Add(Producto1):sc.Productos.Add(Producto2) Return View(sc) End Function

    De que manera se puede generar la Vista de  una "manera dinamica", dependiendo de los productos que se incluyen el el modelo pasado??????????????





    jueves, 30 de agosto de 2012 8:49

Respuestas

  • No hay nada incorrecto en lo que haces (aunque tan solo editas UN ELEMENTO, no? El primero...).

    Pero hay un modo de hacerlo "automatizado" :D

    En view/shared crea una carpeta llamada: EditorTemplates

    Coloca dentro de esta carpeta las dos vistas parciales, pero cambiales el nombre para que se llamen Producto1.vbhtml y Producto2.vbhtml

    Modifica el código de tu vista principal para que sea:

    @Using Html.BeginForm()
        @<div>
            <fieldset>
                <legend>Datos Generales</legend>
                <div class="editor-label">
                    @Html.LabelFor(Function(m) m.Nombre)
                </div>
                <div class="editor-field">
                    @Html.TextBoxFor(Function(m) m.Nombre)
                    @Html.ValidationMessageFor(Function(m) m.nombre)
                </div>
                @Html.EditorFor(Function(m) Model.Productos.First)
    	    <p>
                    <input type="submit" value="Validar" />
                </p>
            </fieldset>
        </div>
    End Using

    Básicamente he modificado tu if(...) por una llamada a EditorFor (revisa la sintaxis, en C# dicha llamada seria (EditorFor(x=>Model.Productos.First()).

    Con eso es el propio fwk de asp.net mvc el que selecciona la vista "parcial" a usar según el tipo real de la variable que se pase a EditorFor (en este caso Productos.First). La condición es que las "vistas parciales" deben estar en Views/Shared/EditorTemplates y llamarse igual que la clase que editan.

    Así si Productos.First es Producto1 se usará Producto1. vbhtml y si es de tipo Producto2 se usará Producto2.vbhtml. Por supuesto eso lo puedes poner dentro de un For Each y se irán mostrando las vistas que toque para cada elemento.

    Si quieres hacer lo mismo pero para "visualizar" y no para editar, entonces la carpeta no es EditorTemplates si no DisplayTemplates y debes usar claro está @Html.DisplayFor. 

    Saludos!

    PD: Puede ser que haya algún error con la sintaxis, no soy muy de VB.NET :)


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis

    • Propuesto como respuesta José M. AguilarMVP domingo, 2 de septiembre de 2012 18:15
    • Marcado como respuesta Eder Costa jueves, 8 de noviembre de 2012 13:51
    viernes, 31 de agosto de 2012 7:45

Todas las respuestas

  • Buenas!

    A que te refieres por generar "de una manera dinámica" la vista dependiendo de los productos? :)

    Saludos!


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis

    jueves, 30 de agosto de 2012 13:00
  • Bien.. Primero, agradecerte tu interes Eduard..

    Te explico.. Segun el ejemplo anterior, yo tengo dos vistas Parciales, llamadas ..

    _vstProducto1.vbhtml

    @ModelType Producto1
    
    <div class="producto">
        Importe mensual @Html.EditorFor(Function(x) x.ImporteMensual) euros 
        <br />
        Nº de meses al año @Html.EditorFor(Function(x) x.Meses)
    </div>
    

    _vstProducto2.vbhtml

    @ModelType Producto2
    
    <div class="producto">
        Importe total @Html.EditorFor(Function(x) x.ImporteAnual) euros 
    </div>
    
    

    Y segun las pruebas que he estado desarrollando, un ejemplo de View seria el siguiente, para poder renderizas partial view, dependiendo de los datos que aparecen en la lista de productos...

    @ModelType Simulador
    
    
    @Using Html.BeginForm()
        @<div>
            <fieldset>
                <legend>Datos Generales</legend>
                <div class="editor-label">
                    @Html.LabelFor(Function(m) m.Nombre)
                </div>
                <div class="editor-field">
                    @Html.TextBoxFor(Function(m) m.Nombre)
                    @Html.ValidationMessageFor(Function(m) m.nombre)
                </div>
    	    @If Model.Productos.OfType(Of Producto1)().Count > 0 Then
                   	@Html.Partial("_vstProducto1", Model.Productos.OfType(Of Producto1))().First)
                End If
                @If Model.Productos.OfType(Of Producto2)().Count > 0 Then
                    @Html.Partial("_vstProducto2", Model.Productos.OfType(Of Producto2)().First)
                End If
                <p>
                    <input type="submit" value="Validar" />
                </p>
            </fieldset>
        </div>
    End Using
    Es aqui donde se plante "mi duda"-... Esta seria una manera correcta de solventar el problema, sin "pisar" el patron MVC?? Ya te digo... Segun lo que he estado leyendo, en las Vistas, mejor omitir "cierta logica" que corresponda al Controlado y/o modelo... No se si te estoy trasladando bien mi duda!!!

    jueves, 30 de agosto de 2012 14:04
  • No hay nada incorrecto en lo que haces (aunque tan solo editas UN ELEMENTO, no? El primero...).

    Pero hay un modo de hacerlo "automatizado" :D

    En view/shared crea una carpeta llamada: EditorTemplates

    Coloca dentro de esta carpeta las dos vistas parciales, pero cambiales el nombre para que se llamen Producto1.vbhtml y Producto2.vbhtml

    Modifica el código de tu vista principal para que sea:

    @Using Html.BeginForm()
        @<div>
            <fieldset>
                <legend>Datos Generales</legend>
                <div class="editor-label">
                    @Html.LabelFor(Function(m) m.Nombre)
                </div>
                <div class="editor-field">
                    @Html.TextBoxFor(Function(m) m.Nombre)
                    @Html.ValidationMessageFor(Function(m) m.nombre)
                </div>
                @Html.EditorFor(Function(m) Model.Productos.First)
    	    <p>
                    <input type="submit" value="Validar" />
                </p>
            </fieldset>
        </div>
    End Using

    Básicamente he modificado tu if(...) por una llamada a EditorFor (revisa la sintaxis, en C# dicha llamada seria (EditorFor(x=>Model.Productos.First()).

    Con eso es el propio fwk de asp.net mvc el que selecciona la vista "parcial" a usar según el tipo real de la variable que se pase a EditorFor (en este caso Productos.First). La condición es que las "vistas parciales" deben estar en Views/Shared/EditorTemplates y llamarse igual que la clase que editan.

    Así si Productos.First es Producto1 se usará Producto1. vbhtml y si es de tipo Producto2 se usará Producto2.vbhtml. Por supuesto eso lo puedes poner dentro de un For Each y se irán mostrando las vistas que toque para cada elemento.

    Si quieres hacer lo mismo pero para "visualizar" y no para editar, entonces la carpeta no es EditorTemplates si no DisplayTemplates y debes usar claro está @Html.DisplayFor. 

    Saludos!

    PD: Puede ser que haya algún error con la sintaxis, no soy muy de VB.NET :)


    Eduard Tomàs Blog: http://geeks.ms/blogs/etomas -- Twitter: eiximenis

    • Propuesto como respuesta José M. AguilarMVP domingo, 2 de septiembre de 2012 18:15
    • Marcado como respuesta Eder Costa jueves, 8 de noviembre de 2012 13:51
    viernes, 31 de agosto de 2012 7:45