Utilizando JQGrid com WebForms    

Olá pessoal!

Muitas pessoas têm dificuldades de utilizar plugins JQuery com WebForms. Principalmente porque desenvolvedor WebForm muitas vezes sabe usar apenas ServerControls, desconhecendo muitos conceitos básicos de Web em sí. Não é a toa que fiz uma série de post nesse blog mostrando conceitos de Web com WebForms.

Geralmente, quando uma pessoa vê exemplos de JQuery, eles estão em PHP, e a pessoa acredita que não funcionaria com WebForms, ou mesmo que saiba que seja possível, não sabe como adaptar para WebForm. Obs.: Geralmente esse problema não acontece com quem desenvolve com Asp.Net MVC.

Nos últimos post, mostrei alguns conceitos que podem ajudar, todos relacionados a PageMethods, como esse e esse. Se você não leu nenhum deles, ou está caindo diretamente nesse post, aconselho fortemente a ler pelo menos esse: Invocando PageMethods diretamente com JQuery.

Se você entender bem esse post que citei, nem precisará desse para utilizar o JQGrid ou qualquer outro plugin JQuery.

Então vamos lá!

Nesse post, vou utilizar as funcionalidades básicas do JQGrid, como Listar, Pesquisar e Editar/Adicionar.

O mais básico, e que todo mundo utiliza, é o Listar. Vou fazer o seguinte no meu HTML/JavaScript:

   1: <script type="text/javascript">
   2:     $().ready(function () {
   3:          $.ajaxSetup({
   4:                dataFilter: function (data, type) {
   5:                    if (type == "json" || type == undefined) {
   6:                        var msg = eval('(' + data + ')');
   7:                        if (msg.hasOwnProperty('d'))
   8:                            return JSON.stringify(msg.d);
   9:                        else
  10:                           return data;
  11:                   }
  12:                   else return data;
  13:               }
  14:            });
  15:  
  16:         $("#tbGrid").jqGrid({
  17:             mtype: "post",
  18:             url: '/Default.aspx/Listar',
  19:             datatype: "json",
  20:             ajaxGridOptions: { contentType: 'application/json; charset=utf-8' },
  21:             colNames: ['ID', 'Nome', 'Idade', 'E-mail'],
  22:             colModel: [
  23:                        { name: 'PessoaID', index: 'PessoaID', width: 55 },
  24:                        { name: 'Nome', index: 'Nome', width: 150 },
  25:                        { name: 'Idade', index: 'Idade', width: 100 },
  26:                        { name: 'Email', index: 'Email', width: 150 }
  27:                    ],
  28:             rowNum: 10,
  29:             rowList: [10, 20, 30],
  30:             pager: '#pager',
  31:             sortname: 'PessoaID',
  32:             viewrecords: true,
  33:             sortorder: "desc",
  34:             caption: "JQGrid com WebForms",
  35:             serializeGridData: function (dados) {
  36:                 return JSON.stringify(dados)
  37:             },
  38:             jsonReader: { repeatitems: false, id: "PessoaID" }
  39:  
  40:         });
  41:         $("#tbGrid").jqGrid('navGrid', '#pager', { edit: false, add: false, del: false });
  42:     });
  43: </script>
  44: <table id="tbGrid">
  45: </table>
  46: <div id="pager">
  47: </div>

Até ai não fiz nada de mais, adicionei configurações padrões na Grid. Adicionei quatro colunas que virão do meu PageMethod, que está na página Default.aspx com o nome Listar.

Como será que deve ficar meu PageMethod para aceitar a requisição dessa Grid? Se não sabe, ai vai uma dica: Utilizando o Fiddler ou o DevelopToolBar, você pode ver qual HTTP Request o Grid está fazendo. Verificando quais campos estão lá você saberá que são os mesmos parâmetros que deve ter no seu PageMethod.

No meu caso, o JQGrid mandou os seguintes campos:

{"_search":false,"nd":1314831637255,"rows":10,"page":1,"sidx":"PessoaID","sord":"desc"}

No meu caso, o que importa é :

  • rows – Representa a quantidade de linha por página.
  • page – Indica a página atual.
  • sidx – Indica o campo pelo qual a Grid está ordenada. Sidx significa Search Index
  • sord – Indica a ordem que o campo definido em sidx deve ser ordenado.

Nesse caso, se meu PageMethod tiver esses campos já será o suficiente. Abaixo segue a implementação dele:

   1: [WebMethod]
   2: public static Reader<Pessoa> Listar( string sidx, string sord, int page, int rows)
   3: {
   4:     var modelo = new Modelo();
   5:     var lista = modelo.Pessoas.ToList();
   6:     var reader = new Reader<Pessoa>(lista,page,rows);
   7:     return reader;
   8: }

Como ele faz a busca, muda de solução para solução. No meu caso eu estou realizando a pesquisa em um SQLServer CE com EntityFramework. Minha classe Reader é responsável por realizar uma “paginação” nos registros retornados e retornar os campos de acordo com o JSONReader da JQGrid. Todo o código fonte dele está abaixo, apenas por curiosidade, visto que você não precisa dele para fazer seu JQGrid funcionar, ele apenas ajuda:

   1: public class Reader<T>
   2: {
   3:    /// <summary>
   4:    /// Número de páginas retornadas no registro
   5:    /// </summary>
   6:    public int total { get; set; }
   7:    /// <summary>
   8:    /// Página atual que a Grid exibirá
   9:    /// </summary>
  10:    public int page { get; set; }
  11:    /// <summary>
  12:    /// Número total de registros na base.
  13:    /// </summary>
  14:    public int records { get; set; }
  15:    /// <summary>
  16:    /// Lista com cada registro.
  17:    /// </summary>
  18:    public List<T> rows { get; set; }
  19:  
  20:    /// <summary>
  21:    /// Construtor recebe a lista e faz a paginação virtual.
  22:    /// </summary>
  23:    /// <param name="lista">Lista com os registros</param>
  24:    /// <param name="paginaAtual">Página atual.</param>
  25:    /// <param name="totalPorPagina">Total de registros por páginas</param>
  26:    public Reader(List<T> lista,int paginaAtual, int totalPorPagina)
  27:    {
  28:  
  29:        var totalRegistros = lista.Count();
  30:        page = paginaAtual;
  31:        var ini = (page - 1) * totalPorPagina;
  32:        var fim = totalRegistros > totalPorPagina ? totalPorPagina : totalRegistros;
  33:        
  34:        if (ini > 0)
  35:        {
  36:            fim = totalPorPagina;
  37:            fim = fim - 10 >= 0 ? totalRegistros % totalPorPagina : fim;
  38:        }
  39:        var totalPags = totalRegistros / totalPorPagina;
  40:        if (totalRegistros % totalPorPagina > 0)
  41:        {
  42:            totalPags++;
  43:        }
  44:        total = totalPags;
  45:        page = page;
  46:        records = totalRegistros;
  47:        rows = lista.ToList().GetRange(ini, fim);
  48:    }
  49: }

Com os códigos acima minha Grid já está funcionando:

image

Se, por exemplo, eu mudo a quantidade de registros por página, a Grid vai passar os novos valores nos parâmetros do PageMethod, e minha pesquisa retornará a nova quantidade de registros por página:

{"_search":false,"nd":1314832264231,"rows":"20","page":1,"sidx":"PessoaID","sord":"desc"}

E se eu quiser utilizar os campos de pesquisa do JQGrid? Será que o PageMethod já está preparado? Vamos ver. Vou buscar pelo usuário de nome “Frederico” na lista da Grid, vamos ver o que a JQGrid envia para o servidor utilizar o Fiddler ou o IEDeveloperToolbar, ou qualquer ferramenta de sua vontade. Utilizando a “Lupa” da Grid e selecionando o campo na popup que aparece:

image

O que ele envia é o seguinte:

{"_search":true,"nd":1314832456208,"rows":"20","page":1,"sidx":"PessoaID","sord":"desc", "searchField":"Nome","searchString":"Frederico","searchOper":"eq","filters":""}

Veja que alguns campos foram adicionados e outros estão com novos valores, os campos que teremos que adicionar em nosso PageMethod são:

  • _seach – Indica se está sendo realizando uma pesquisa ou se é apenas a listagem do dados
  • searchField – Indica por qual campo está sendo pesquisado.
  • searchString – Indica qual é o valor pesquisado.
  • searchOper – Indica qual é o operado utilizado para a pesquisa.

Vou alterar meu PageMethod  para ficar da seguinte forma:

   1: [WebMethod]
   2: public static Reader<Pessoa> Listar(GridParams param)
   3: {
   4:     var modelo = new Modelo();
   5:     List<Pessoa> lista;
   6:  
   7:     if (param._search)
   8:     {
   9:         var operador = new Func<string,string,string>((op,valor) =>
  10:         {
  11:              int saida;
  12:              bool isNum = Int32.TryParse(valor, out saida);
  13:             switch(op){
  14:                 case "ne":
  15:                     return isNum? string.Format(" <>{0}", valor): string.Format(" <>\"{0}\"", valor);
  16:                 default:
  17:                     return isNum ? string.Format(" = {0}", valor) : string.Format(" = \"{0}\"", valor);
  18:                 }
  19:         });
  20:  
  21:         var sb = new StringBuilder();
  22:         sb.Append(param.searchField);
  23:         sb.Append(operador(param.searchOper,param.searchString));
  24:         lista = modelo.Pessoas.Where(sb.ToString()).ToList();
  25:     }
  26:     else{
  27:         lista = modelo.Pessoas.ToList();
  28:     }
  29:     
  30:     var reader = new Reader<Pessoa>(lista, param.page, param.rows);
  31:     return reader;
  32: }

Primeira mudança importante é que troquei todos os parâmetros por uma classe. A classe encapsula todos aqueles campos que a JQGrid envia para o servidor, independente do Request. Apesar de ser bem simples, segue o código:

   1: public class GridParams
   2: {
   3:     public string sidx;
   4:     public string sord;
   5:     public int page;
   6:     public int rows;
   7:     public bool _search;
   8:     public string searchField;
   9:     public string searchString;
  10:     public string searchOper;
  11: }

Criei essa classe para receber todos os parâmetros porque o Asp.Net não aceita WebServices/PageMethods com parâmetros opcionais ou com Overloads, então criei um método com apenas um parâmetro, que pode ter todos os campos definidos ou não. Visto que a JQGrid utiliza o mesmo método para listar e pesquisar, essa é a única solução.

O resto é apenas a lógica do método, que você pode mudar com a sua no lugar, a minha é só para exemplo. O segredo está em validar o parâmetro _search, se ele for true quer dizer que o usuário está realizando uma pesquisa, e não apenas carregando a lista. Para simular, criei apenas lógica necessária para o usuário usar um Campo como critério igual ou diferente do valor que for fornecido.

Com isso minha lógica já estará funcionando.

Como mudei o parâmetro do PageMethod, preciso apenas alterar um evento na configuração da Grid, para encapsular o nome do parâmetro:

   1: serializeGridData: function (dados) {
   2:    return JSON.stringify({param: dados})
   3: },

Esse evento é invocado pela Grid logo antes da requisição ser enviada para o servidor, então eu coloco os parâmetros dentro do campo param. E pronto! sua Grid está funcionando perfeitamente com Asp.Net WebForm.

Para finalizar, vamos fazer a Grid conseguir criar e alterar registros

Adicionando  e Alterando registro com JQGrid

Antes de mais nada, devo habilitar algumas configurações no Pager da grid, fazendo que o botão de adicionar e editar apareça:

   1: $("#tbGrid").jqGrid('navGrid', '#pager', { edit: true, add: true, del: false });

E alterar o ColModel para dizer como será a edição de cada campo:

   1: colModel: [
   2:    { name: 'PessoaID', index: 'PessoaID', width: 55, editable: false, editoptions: { readonly: true, size: 10} },
   3:    { name: 'Nome', index: 'Nome', width: 150, editable: true, editoptions: { size: 50} },
   4:    { name: 'Idade', index: 'Idade', width: 100, editable: true, editoptions: { size: 2 }, editrules: {integer:true} },
   5:    { name: 'Email', index: 'Email', width: 150, editable: true, editoptions: { size: 50 }, editrules: { email: true} }
   6: ],

Depois adicionar a opção para definir o caminho do PageMethod responsável por salvar o registro:

   1: editurl: "/Default.aspx/Salvar"

Também devemos alterar algumas configurações da Grid para conseguir tratar o JSON, porque infelizmente o JQuery tem um problema ao converter os dados para JSON automaticamente, então nós mesmos temos que fazer isso. Para isso, vamos alterar algumas informações padrões da Grid:

   1: $.extend($.jgrid.edit,
   2: {
   3:     ajaxEditOptions: { contentType: "application/json;charset=utf-8" },
   4:     serializeEditData: function (data) {
   5:         return JSON.stringify(data);
   6:     }
   7: });

Feito isso, não precisamos mais fazer nada no JavaScript, apenas preparar o PageMethod. que você verá que é autoexplicativo:

   1: [WebMethod]
   2: public static void Salvar(string Nome, int Idade, string Email, string oper, string id)
   3: {
   4:     var modelo = new Modelo();
   5:     if (oper == "add")
   6:     {
   7:         var pessoa = new Pessoa
   8:         {
   9:             Nome = Nome,
  10:             Idade = Idade,
  11:             Email = Email
  12:         };
  13:         modelo.Pessoas.Add(pessoa);
  14:     }
  15:     else
  16:     {
  17:         var pessoa = modelo.Pessoas.Where("PessoaID = " + id).ToList()[0];
  18:         pessoa.Nome = Nome;
  19:         pessoa.Idade = Idade;
  20:         pessoa.Email = Email;
  21:     }
  22:     modelo.SaveChanges();
  23: }

E pronto!

Com isso você já pode testar a alteração e inclusão clicando nos botões que aparecem na barra da Grid:

Alterando registro com JQGrid X WebForms

Criando registro com JQGrid X WebForms

É isso pessoal, com o que foi passado nesse post você já consegue ir muito além. Você viu que tudo é possível com a estrutura que o Asp.Net fornece para o WebForm.

Espero que isso ajude. Muitas pessoas já me perguntaram sobre JQGrid com WebForm, isso deve ajudar muita gente.

Abraços e até o próximo!

 

::Atualização

Estou publicando o exemplo do código para esclarecer as dúvidas de alguns. Qualquer problema, comente ai embaixo.

Abs.

JQGridWebForm.zip (3,04 mb)

2. setembro 2011 00:39 by Frederico B. Emídio | Comments (15) | Permalink

Comments

brm
Olá Frederico, parabéns pela sua iniciativa ao levar seu conhecimento para muitos, como é o meu caso, sou iniciante em .NET e com certeza seu blog esta sendo de muita valia para meu aprendizado. Já adicionei nos favoritos. Obrigado.
11/09/2011 18:51:56 #
Juliano
Caro Frederico eu não consegui executar a parte do update ficou faltando algo em meu script pois esta gerando um erro #404
teria como você estar me enviando o script que você utilizou neste exemplo desde já agradesço.
16/11/2011 23:40:58 #
Marcos William
Olá Frederico,
Excelente trabalho, mas eu não entendi o que é essa classe Modelo que vc usa. Eu estou usando o JQGrid com VB.net e não sei como fazer isso modelo.Pessoas.Where(sb.ToString()).ToList();

O que tem nessa classe Modelo que vc usa ?

Obrigado.
30/11/2011 20:02:29 #
Olá Marcos!

Essa classe modelo representa meu modelo de Dados, no caso criei um modelo de dados com Entity Framework CodeFirst.

Mas você pode utilizar qualquer coisa para representar seu modelo de dados. Se você reparar, estou apenas criando e pesquisando registros nesse método para preencher a grid, você pode utilizar como quiser.

Por exemplo, você poderia usar ADODB.NET diretamente, ou utilizar o Data Application Block da MS, ou NHIbernate, não importa, o que importa é que nos métodos Listar ou Salvar, você irá realizar uma pesquisa na sua base de dados ou incluir um novo registro nela, da forma que você se sentir mais a vontade.

Abs,
Frederico
01/12/2011 03:40:29 #
wagner
Ola Frederico este exemplo ta muito legal, mais não estou conseguindo fazer funcionar.

ta dando erro nesta parte aqui "dataFilter: function (data, type) {". pode me dar uma ajuda me falar as versões usadas do jquery e do jgrid ou me mostra o aspx inteiro alguem ai pode me ajudar????
19/05/2012 22:44:51 #
Wagner, respondido por e-mail.
Abs,
20/08/2012 07:33:45 #
Marcos Agostta
Boa tarde, Primeiramente gostei muito do tutorial, parabéns continue assim. Queria saber você pode me ajudar com excluir, ja faz um tempo que estou tentando. Eu alterei o #pager e adicionei um "$.extend($.jgrid.del .." para trabalhar com o json, porém o método invocado é o do urledit e a quantidade de parâmetros é diferente. já que os parâmetros da exclusão são um oper e um id. Att.
31/10/2012 01:20:43 #
Marcos William
Olá Marcos Agostta,
Creio que a verificação de que ação tomar tem que estar dentro do método no serverSide.
No exemplo de Frederico, no método Salvar,tem isto na linha 5:

if (oper == "add")

Esta "oper" vem com o valor "del".
O mesmo acontece com o edit.

Espero ter ajudado.
Att.
31/10/2012 03:16:12 #
Obrigado pela resposta Marcos William! Vamos conferir com o Agostta se isso resolve o problema dele.

Abs,
Fred
31/10/2012 03:24:26 #
Amigos, por favor vejam se conseguem me ajudar.

A Grid aqui funciona 100%, mas estou tentando esconder a coluna ID, para que o Usuário do Sistema não a veja. Alguém sabe como escondê-lo?

No aguardo.
Obrigado desde já.
13/11/2012 01:02:01 #
Com relação ao comentário do Marcos Agosta, acredito que o Marcos Wilian entendeu diferente.

Pelo que entendi, o problema do Marcos Agosta é que o método "Salvar" tem em sua assinatura 5 parâmetros. Porém quando executamos a exclusão, ele passa apenas 2 parâmetros.

Imaginei que usando parâmetros opcionais resolveria, mas aqui pelo menos não resolveu. Ele acusa que está faltando os parâmetros que não passei, mesmo declarando eles como opcional.

att,
13/11/2012 01:08:50 #
Wagner Silva
Bruno Pereira ve se isso ajuda.

{ name: 'Id', index: 'Id', width: 75, hidden: true, search: false, searchoptions: {searchhidden: true} },
13/11/2012 01:45:06 #
Obrigado Wagner Silva, genial, funcionou. Vlw. Agora preciso resolver o esquema do Excluir. Abraço
13/11/2012 02:00:37 #
Muito bom pessoal!

Valeu pela interação ai, se tiverem algum problema, pode enviar e-mail, mas pelo visto vocês consegue tocar pelos comentários.

Em breve virão mais posts!

Abs,
Frederico
13/11/2012 03:11:27 #
Allan
Boa tarde Frederico. Estou tentando utilizar jqgrid para um projeto na faculdade. Sou iniciante em asp.net e estou utilizando entity framework. Criei um banco de dados que gerou o arquivo pessoa.mdf.
Após a criação do banco, adaptei o projeto baseado no seu código. Criei o entity framework que me gerou o arquivo model.edmx.

Após muito sofrimento consegui fazer listar os registros na jqgrid. Utilizei o seguinte comando:
public static Reader<Pessoa> Listar(GridParams param)
        {
            using (PessoaEntities ctx = new PessoaEntities())
            {
                 var dados_pessoas = ctx.Pessoas.ToList();
                 var reader = new Reader<Pessoa>                     (dados_pessoas, param.page, param.rows);
                 return reader;
            }
        }

Através dessa modificação consegui listar na tabela, mas quando tento adaptar para pesquisar ou alterar/incluir aparece erro.
Estou tentando adaptar o seguinte comando:
var sb = new StringBuilder();
sb.Append(param.searchField);
sb.Append(operador(param.searchOper, param.searchString));

var dados_pessoas = ctx.Pessoas.where(sb.tostring()).ToList();

O erro que aparece é o seguinte:
'System.Data.Entity.DbSet<WebApplication1.Pessoa>' does not contain a definition for 'Where'

Você poderia me dar alguma dica de como implementar estes códigos utilizando o entity framework ?

Desde já  lhe agradeço pela atenção.

Obrigado,  Allan.

10/10/2013 01:48:49 #
Comments are closed

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  novembro 2017  >>
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET