Mais uma vez recebi algumas dúvidas sobre ASP.NET MVC e vou compartilhar com todos a resposta que eu dei, desta vez a dúvida foi de como fazer um conjunto de DropDownList em cascata.
O que me parece recorrente na maioria das dúvidas que eu recebo em relação ao ASP.NET MVC, é que as dúvidas sempre estão no lado do cliente, no WebForms poderíamos configurar a propriedade AutoPostBack para True do DropDowList e tratar o resto no lado do servidor, no MVC é diferente, você vai ter que escrever um pouco de JavaScript para fazer isso, vamos analisar o problema e criar um cenário.
Vamos fazer uma página que terá um DropDownList com uma relação de estados e quando for selecionado o estado listaremos no outro DropDownList a relação de cidades.
Para isso quando a página for renderizada pela primeira vez já iremos trazer o DropDownList de Estados carregado e iremos carregar o de Cidades com jQuery/Ajax.
Para fazer isso vamos criar as nossas classes do modelo, na pasta “models” crie as classes abaixo:
Uf.cs:
public class Uf { public Uf(string siglaUf, string nome) { this.Nome = nome; this.SiglaUf = siglaUf; } public string SiglaUf { get; set; } public string Nome { get; set; } }
Cidade.cs
public class Cidade { public Cidade(string id,string siglaUf, string nome) { this.Id = id; this.SiglaUf = siglaUf; this.Nome = nome; } public string Id { get; set; } public string SiglaUf { get; set; } public string Nome { get; set; } }
Vamos criar agora 2 classes de repositório, para facilitar a consulta no exemplo, crie as 2 classes abaixo na pasta “models”:
UfRepository.cs
public class UfRepository { public static IList<Uf> ListaUf() { List<Uf> cidades = new List<Uf>(); cidades.Add(new Uf("SP", "São Paulo")); cidades.Add(new Uf("RJ", "Rio de Janeiro")); cidades.Add(new Uf("MG", "Minas Gerais")); return cidades; } }
CidadeRepository.cs
public class CidadeRepository { public static IList<Cidade> ListaCidade(string SiglaUf) { List<Cidade> cidades = new List<Cidade>(); cidades.Add(new Cidade("1","RJ", "Angra dos Reis")); cidades.Add(new Cidade("2", "RJ", "Rio de Janeiro")); cidades.Add(new Cidade("3", "RJ", "Barra Mansa")); cidades.Add(new Cidade("4","SP", "São Paulo")); cidades.Add(new Cidade("5", "SP", "Sertãozinho")); cidades.Add(new Cidade("6", "SP", "Osasco")); cidades.Add(new Cidade("7", "MG", "Belo Horizonte")); cidades.Add(new Cidade("8", "MG", "Poços de Caldas")); cidades.Add(new Cidade("9", "MG", "Betim")); return cidades.Where(x=> x.SiglaUf==SiglaUf).ToList(); } }
Agora vamos modificar o arquivo Site.Master que está na pasta ViewsShared, esta modificação é só para acrescentar a referência para o arquivo do jQuery e criar um ContentPlaceHolder para acrescentarmos o JavaScript necessário na nossa View.
Site.Master (linhas 5 e 6)
<head runat="server"> <title><asp:ContentPlaceHolder ID="TitleContent" runat="server" /></title> <link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> <script src="../../Scripts/jquery-1.3.2.js" type="text/javascript"></script> <asp:ContentPlaceHolder ID="HeadContent" runat="server"></asp:ContentPlaceHolder> </head>
Como falado acima precisamos que na primeira renderização da página ela carregue a lista de estados, para isso precisamos carregar esta lista para a View, vou fazer isso através da ViewData[“Ufs”], irei fazer isso na Action Index da HomeController (se ainda não foi feito, adicione um using para o namespace Models no começo da sua classe), veja no exemplo abaixo:
public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; ViewData["Ufs"] = new SelectList(UfRepository.ListaUf(),"SiglaUf","Nome"); return View(); }
Agora poderemos já começar a fazer o HTML, para isso acrescente o código na View Index da pasta Home conforme o exemplo abaixo:
<% =Html.DropDownList("Ufs","Estado") %> <select id="Cidades"> <option selected="selected" value="">Cidade</option> </select>
Como vocês podem perceber na primeira linha, estou criando um DropDownList passando somente 2 parâmetros, o método tentará encontrar uma ViewData com o nome passado no primeiro parâmetro e irá tentar converter esta ViewData para um objeto SelectList, não vou me aprofundar muito para não fugir do escopo, em outro post irei falar mais detalhadamente sobre o DropDownList e SelectList.
Se você testar, verificará que o primeiro DropDownList já está carregando, mas quando mudamos o item selecionado nada acontece, para fazer isso devemos escrever um pouquinho de JavaScript, para facilitar este trabalho iremos usar o jQuery e fazer uma chamada Ajax para uma Action que retorna um JSON.
Vamos começar criando uma Action chamada ListarCidade na HomeController que irá receber no parâmetro id o estado que foi selecionado e irá retornar uma lista de cidades que são daquele estado conforme o código abaixo:
public ActionResult ListaCidade(string id) { return Json(CidadeRepository.ListaCidade(id)); }
Voltando na View Index na pasta Home vamos acrescentar o JavaScript necessário para fazer a chamada Ajax via jQuery, segue o código:
<asp:Content ID="Javascript" ContentPlaceHolderID="HeadContent" runat="server"> <script type="text/javascript"> $(document).ready(function() { $("#Ufs").change(function() { listaCidade($(this).val()); }); }); //chamada ajax para a Action ListaCidade //passando como parâmetro a Estado selecionado function listaCidade(uf) { $.getJSON('<%= Url.Action("ListaCidade") %>/' + uf, listaCidadeCallBack); } //função que irá ser chamada quando terminar //a chamada ajax function listaCidadeCallBack(json) { //Limpar os itens que são maiores que 0 //Ou seja: não retirar o primeiro item $("#Cidades :gt(0)").remove(); $(json).each(function() { //adicionando as opções de acordo com o retorno $("#Cidades").append("<option value='" + this.Id + "'>" + this.Nome + "</option>"); }); } </script> </asp:Content>
Está pronto, é claro que não é mais fácil que o WebForms, mas o controle te traz mais responsabilidades, você vai ter que fazer (e conhecer) mais HTML e Javascript, não tem jeito.
Faça o download da solução.
Victor Cavalcante
Victor Cavalcante é marido da Mariana Frioli, pai do Eduardo, Microsoft MVP, trabalha com desenvolvimento web a 11 anos e é focado em padrões de desenvolvimento para web. Trabalha na Lambda3 (www.lambda3.com.br), empresa ágil que insiste em fazer software certo. É ainda professor universitário e atua no grupo .NET Architects desde seu início. Acompanhe seu twitter para saber as novidades:@vcavalcante.