RSS

ASP.NET MVC – Criando Views Genéricas e com Campos Dinâmicos

27 ago

Isso mesmo, neste post demonstrarei como podemos criar uma View genérica, ou seja, que possa ser utilizada de diversas formas, com renderização dos campos de acordo com sua utilidade (campos dinâmicos) e com uma fácil implementação.

Mas você deve estar se perguntado, “Para que eu utilizaria uma View genérica em meu projeto?”. A resposta é fácil e com um simples exemplo fica fácil de responder.

Imagine uma solução onde existam dezenas de relatórios, onde cada um possua parâmetros específicos. Dependendo da forma de desenvolvimento, pode ficar algo um tanto quanto trabalhoso para se programar o preenchimento de cada um. Agora imagine a solução onde você selecionaria o relatório e seus parâmetros já viessem renderizados automaticamente em sua View. Ou até mesmo uma Classe de Usuários com seus campos já renderizados, e ao alterar para uma Classe Clientes por exemplo, na mesma View já vier renderizados os campos apenas do Cliente.

A forma de utilização/implementação e utilidade depende da necessidade de cada um, mas vamos lá!

Como podemos observar abaixo em nosso banco, possuímos apenas duas tabelas (Usuarios e Clientes), note que temos campos dos tipos varchar, int, datetime, bit e decimal:

Figura 1

Vamos criar agora um novo projeto ASP.NET MVC 3 e criar um novo arquivo do tipo ADO.Entity Data Model dentro do diretório Models, após referenciar nossas tabelas nele, conforme a imagem abaixo:

 

Figura 2

Em seguida vamos criar uma classe chamada CampoDinamico.cs no mesmo diretório, segue código da classe:

Observe que estamos utilizando a referencia “System.Data.Metadata.Edm”, isto para que seja possível obter  a propriedade “EdmProperty” da nossa entidade do EDMX, ou seja, através desta propriedade iremos obter o nome do campo, se o mesmo aceita valores null, o tipo, etc.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Data.Metadata.Edm;

namespace MVC3.Models
{
    public class ValorDinamico
    {
        public string Value { get; set; }
        public string Text { get; set; }

        public ValorDinamico(string valor, string texto)
        {
            Text = texto;
            Value = valor;
        }
    }

    public class CampoDinamico
    {
        public string prompt { get; set; }
        public string nome { get; set; }
        public string tipo { get; set; }
        public bool requerido { get; set; }

        public CampoDinamico(EdmProperty p)
        {
            this.prompt = p.Name.Replace("@", "");
            this.nome = p.Name.Replace("@", "");
            this.requerido = p.Nullable ? false : true;

            switch (p.TypeUsage.EdmType.ToString().ToLower())
            {
                case "edm.varchar":
                case "edm.string":
                    this.tipo = "String";
                    break;

                case "edm.datetime":
                    this.tipo = "Date";
                    break;

                case "edm.decimal":
                    this.tipo = "Decimal";
                    break;
                case "edm.int":
                case "edm.int16":
                case "edm.int32":
                    this.tipo = "Int";
                    break;

                default:
                    this.tipo = "String";
                    break;
            }
        }

        public CampoDinamico(string prompt, string nome, string tipo)
        {
            this.prompt = prompt;
            this.nome = nome;
            this.tipo = tipo;
        }
    }
}

Agora em nosso HomeController.cs vamos criar uma Action, que no caso será nossa action genérica, em seguida explicarei cada etapa da mesma:

public TesteDB db = new TesteDB();

        public ActionResult ViewGenerica(string formulario)
        {
            List<EdmProperty> properties = null;

            switch (formulario)
            {
                case "Usuario":
                    properties = db.tbUsuarios.EntitySet.ElementType.Properties.ToList();
                    break;

                case "Cliente":
                    properties = db.tbClientes.EntitySet.ElementType.Properties.ToList();
                    break;
            }

            List<CampoDinamico> campos = (from p in properties select new CampoDinamico(p)).ToList();

            return View(campos);
        }


1º – Note que, é recebido como parâmetro uma string, que no caso é o tipo do formulário que vamos carregar.

2º – É criada uma lista do tipo EdmProperty, está lista ira armazenar as propriedades do tipos das nossas entidades do EDMX.

3º – Em seguida é realizada uma verificação do tipo do formulário solicitado, e seleciona para cada escolha as propriedades equivalentes na entidade.

4º – Por fim é criada uma nova lista do tipo CampoDinamico que recebe os respectivos objetos criados.

Vamos agora criar nossa View, segue abaixo o código da ViewGenerica:

@model IEnumerable<MVC3.Models.CampoDinamico>

@{
    ViewBag.Title = "View Generica";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>ViewGenerica</h2>
<div>
    @{Html.RenderPartial("FormDinamico", Model);}
</div>

Observe que estamos chamando um UserControl chamado FormDinamico, vamos cria-lo também:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IList<MVC3.Models.CampoDinamico>>" %>

<table>
<%
    foreach (MVC3.Models.CampoDinamico cd in Model)
    {
        %>
        <tr>
            <td><% Html.RenderPartial("LabelDinamico", cd);%></td>
            <td><% Html.RenderPartial("CampoDinamico", cd);%></td>
        </tr>
        <%
    }
%>
</table>

Em seguida criamos os UserControls CampoDinamico e LabelDinamico:

CampoDinamico

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<div>

    <% if (!String.IsNullOrEmpty(Model.prompt))
        Html.RenderPartial("CampoDinamico" + Model.tipo, Model);%>

</div>

LabelDinamico

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%=Html.Label(Model.nome)%>

No UserControl CampoDinamico note que, é chamado um outro UserControl concatenando o tipo do campo ao nome, por tanto vamos criar um UserControl para cada tipo de campo, ou seja, cada UserControl ficará responsável por renderizar seu tipo de campo:

CampoDinamicoInt

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%=Html.TextBox(Model.nome)%>

<script type="text/javascript">
    $(document).ready(function () {

        $('#<%=Model.nome%>').number();

    });
</script>

CampoDinamicoDecimal

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%=Html.TextBox(Model.nome)%>

<script type="text/javascript">
    $(document).ready(function () {

        $('#<%=Model.nome%>').maskMoney({ showSymbol: false });

    });
</script>

CampoDinamicoDate

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%=Html.TextBox(Model.nome)%>

<script type="text/javascript">
    $(document).ready(function() {

        $('#<%=Model.nome%>').mask('99/99/9999');

    });
</script>

CampoDinamicoString

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%= Html.TextBox(Model.nome, "") %>

CampoDinamicoCheckBox

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MVC3.Models.CampoDinamico>" %>

<%=Html.CheckBox(Model.nome)%>

Colocamos também validações jQuery para cada UserControl para um melhor controle, a estilização e design fica a gosto de cada um 🙂

Pronto, agora apenas para testar vamos criar dois links em nossa Index:

@Html.ActionLink("Usuario", "ViewGenerica", new { formulario = "Usuario" })
@Html.ActionLink("Cliente", "ViewGenerica", new { formulario = "Cliente" })
<br />
<br />
@Html.ActionLink("Voltar", "Index")

Observe, tanto para o link de Cliente quanto para Usuário, as propriedades especificas de ambos são renderizadas na mesma View:

Figura 3

Figura 4 – Campos do usuário

Figura 5 – Campos do cliente

Fica ai a dica 🙂

Até a próxima!

Download do projeto AQUI.


Anúncios
 

Tags: , , ,

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

 
%d blogueiros gostam disto: