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.