Filtros dinâmicos em listagem de registros

.NET

07/06/2012

Boa noite, pessoal!

Estou fazendo uma página (C#, MVC) que lista registros de uma tabela. Eu adicionei textBoxs e DropDownLists para o usuário fazer filtros sobre as colunas que estão em exibição na página.

O usuário, entretanto, pode querer utilizar o filtro apenas em uma ou algumas colunas. Eu não consegui pensar num jeito de programar isso de forma elegante... olha o que eu fiz:


No meu Controller:

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Index(FormCollection collection)
        {
            //Pega o valor a ser procurado no campo resumo da tabela
            string searchResumo = collection[searchResumo];
            //Pega o id do Status selecionado pelo usuário no Drop Down List
            string searchStatus = collection[AtividadeStatusID];
            //Chama o método para pegar os registros com os critérios selecionados pelo usuário - AQUI COMEÇA O PROBLEMA
                var atividades = atividadeRepository.FindAtividades(searchResumo, searchStatus);   
                return View(AtividadeListView, atividades); 
            }
        }


Na minha classe .c está assim:
        public IQueryable<Atividade> FindAllAtividadesResumo(string resumoProcurado, string idStatus)
        {

            return from atividade in db.Atividades
                    where atividade.resumo.Contains (resumoProcurado) && atividade.AtividadeStatusID == idStatus
                    orderby atividade.dataCriacao
                    select atividade;
        }


A questão é... se o usuário informar só um resumo procurado e nenhum status??? Ou se informar só um status e nenhum resumo procurado???

Eu pensei em usar vários IF´s para resolver isso, mas ía ficar horrível, ainda mais se eu quisesse aumentar as possibilidades de filtragem...

Deve existir alguma solução ou algum design que resolva este meu problema, só não consegui encontrar...


Alguém tem alguma idéia???

Valeu!!!
Felipe Bulle

Felipe Bulle

Curtidas 0

Respostas

Joel Rodrigues

Joel Rodrigues

07/06/2012

Não vejo outra forma rápida a não ser verificar se os parâmetros são nulos e filtrar apenas pelos parâmetros não nulos.
GOSTEI 0
Felipe Bulle

Felipe Bulle

07/06/2012

Obrigado pelo retorno!

Até aí sem problemas... o problema é que não sei se estou fazendo isso da melhor forma. Seria algo parecido com isso:

public IQueryable<Atividade> FindAllAtividadesResumo(string resumoProcurado, string idStatus)
{

     if (string.isNullOrEmpty(resumoProcurado) && string.isNullOrEmpty(resumoProcurado)){
        return from atividade in db.Atividades
        orderby atividade.dataCriacao
        select atividade;

     }elseif (string.isNullOrEmpty(resumoProcurado)){
        return from atividade in db.Atividades
        where atividade.AtividadeStatusID == idStatus
        orderby atividade.dataCriacao
        select atividade;
   
     }elseif (string.isNullOrEmpty(idStatus)){
        return from atividade in db.Atividades
        where atividade.resumo.Contains (resumoProcurado)
        orderby atividade.dataCriacao
        select atividade;

     }else{
        return from atividade in db.Atividades
        where atividade.resumo.Contains (resumoProcurado) && atividade.AtividadeStatusID == idStatus
        orderby atividade.dataCriacao
        select atividade;
     }
}


Ou teria uma forma melhor? Porque se eu aumentar o número de critérios, estou ferrado... rs...


Mais uma vez, obrigado!
GOSTEI 0
Rachel Andrade

Rachel Andrade

07/06/2012

Assim, não pude testar aqui... mas me veio uma ideia à cabeça e vou compartilhar com você. Analise o seguinte código e veja o que acha dele:
IQueryable<Atividade> consulta = null;
//Todos os dados, sem filtro
consulta = from atividade in db.Atividades
orderby atividade.dataCriacao
select atividade;

if (string.isNullOrEmpty(resumoProcurado)){
consulta = from atividade in db.Atividades
where atividade.AtividadeStatusID == idStatus
orderby atividade.dataCriacao
select atividade;

if (string.isNullOrEmpty(idStatus)){
consulta = from atividade in db.Atividades
where atividade.resumo.Contains (resumoProcurado)
orderby atividade.dataCriacao
select atividade;

//...demais filtros

return consulta;


Ou seja, vc inicia com a lista completa e vai filtrando de acordo com os parâmetros não nulos sequencialmente, o que terminar por ter o mesmo efeito que um AND.

GOSTEI 0
Joel Rodrigues

Joel Rodrigues

07/06/2012

Poxa, Rachel, lendo meus pensamentos? rsrs
Eu também ia sugerir isso, mas adicionaria uma dica: use expressões Lambda, pode ser que enxugue mais o seu código.
GOSTEI 0
Felipe Bulle

Felipe Bulle

07/06/2012

Oi Rachel!

Valeu pela dica...

Só uma dúvida para confirmar...

Eu vi que primeiro você coloca todos os dados sem filtro...

Aí você vai recarregando a variável consulta conforme os valores que tiverem que ser filtrados... Mas quando você coloca na variável consulta, por exemplo:

consulta = from atividade in db.Atividades
where atividade.AtividadeStatusID == idStatus
orderby atividade.dataCriacao
select atividade;


e depois você faz de novo:


consulta = from atividade in db.Atividades
where atividade.resumo.Contains (resumoProcurado)
orderby atividade.dataCriacao
select atividade;


isso não vai anular o efeito da primeira atribuição? Ou vai ter efeito de uma concatenação de AND´s???

Mais uma vez obrigado!!!

GOSTEI 0
Joel Rodrigues

Joel Rodrigues

07/06/2012

Acho que a colega se confundiu um pouco. =)
Ao invés de db.Atividades, você passa a fazer os filtros sobre a variável consulta.

Boa sorte.
GOSTEI 0
Joel Rodrigues

Joel Rodrigues

07/06/2012

Acho que a colega se confundiu um pouco. =)
Ao invés de db.Atividades, você passa a fazer os filtros sobre a variável consulta.

Boa sorte.
GOSTEI 0
Joel Rodrigues

Joel Rodrigues

07/06/2012

Saca só como ficaria com Lambda Expressions:
//Todos os dados, sem filtro
var consulta = db.Atividades;

if (!String.IsNullOrEmpty(idStatus))
consulta = consulta.Where(a => a.AtividadeStatusID == idStatus);


if (!String.IsNullOrEmpty(resumoProcurado){
consulta = consulta.Where(a => a.Resumo.Contains(resumoProcurado));

//...demais filtros

return consulta;


Boa sorte.
GOSTEI 0
Felipe Bulle

Felipe Bulle

07/06/2012

Pessoal, muito obrigado a todos pela força!

Aprendi muito!

Resolvido!

Abraço!
GOSTEI 0
Joel Rodrigues

Joel Rodrigues

07/06/2012

Que bom que deu certo, cara, ficamos felizes em ter ajudado.
Boa sorte em seus projetos.
GOSTEI 0
POSTAR