function MVXDataGrid(Nome, Tabela, ID, Estilo, Container, Comandos) 
{
  // Inicializa propriedades. Algumas delas tem seu valor já definido, outras são setadas para null.
  this.Nome = Nome;
  this.Tabela = Tabela;
  this.ID = ID;
  this.Estilo = Estilo;
  this.Container = Container;
  this.Comandos = Comandos;

  // Associação dos métodos. Fazemos assim, para poder usá-los mesmo antes deles serem implementados.
  this.Inicializa = Inicializa;
  this.Popula = Popula;
  this.Inicializa();

  // Método que inicializa o objeto.
  function Inicializa()
  {
    this.Popula(null);
  }


  // Popula o listbox, utilizando os filtros padrão associados, e opcionalmente o texto existente no textbox, ou ainda
  // um ItemID que pode ter sido passado (se existir ItemID, ele ignora o texto presente no textbox).
  function Popula(Ordem, Pagina, NumRegistrosPagina)
  {
        /*
    // Vamos começar criando um array de filtros, e checando a existência de um ItemID.
    var FiltrosProcessados = new Array();
    if(is_int(ItemID))
      // Se ele existir, um filtro é adicionado, especificando que queremos apenas o item indicado por ItemID. 
      // À primeira vista, este seria o único filtro necessário quando queremos apenas um item em particular, mas
      // os filtros associados são necessários para nos certificarmos de que o ItemID indicado realmente está 
      // relacionado com as outras entidades envolvidas no contexto. O campo "valor" deve ser hardcoded, porque a rotina
      // server-side sempre chama de "valor" o campo que contém o texto de exibição do combobox.
      FiltrosProcessados.push("valor="+ItemID);
    else if(this.ElementoTexto.value.length >= GLMVXComboBoxNumMinCaracteres)
      // Se não houver ItemID, mas houver conteúdo no textbox, faremos o filtro através dele, desde que ele tenha 
      // o tamanho mínimo exigido. O campo "nome" deve ser hardcoded, porque a rotina server-side sempre chama de "nome" 
      // o campo que contém o texto de exibição do combobox.
      FiltrosProcessados.push("nome like '%"+this.ElementoTexto.value+"%'");
    else
      // Se não foi passado nenhum ID, e se o texto existente em textbox não atende aos requisitos mínimos, 
      // devemos abortar o processo, sem preencher o listbox.
      return;
    
    // Agora vamos começar a tratar os filtros associados ao controle, inicializando algumas variáveis auxiliares.
    var Valor;
    var FiltrosAusentes = false;
    // Agora faremos um loop por cada filtro definido dentro do elemento. Os filtros sempre referem-se a valores de outros
    // elementos existentes no mesmo formulário, portanto, nem sempre estão presentes.
    for(i in this.Filtros)
    {
      // Vamos obter o valor do controle referenciado neste filtro.
      Valor = GetElementoID(this.Filtros[i][1]).value;
      // Vamos checar se o valor é nulo ou vazio.
      if(is_null(Valor) || Valor == '')
      {
        // Se for, isto significa que, para preencher este combo, precisamos do valor de um controle que ainda não foi
        // setado, ou pior, que o controle não existe no form, o que é um bug, e não pode acontecer. 
        // De qualquer forma, existe um filtro ausente. A flag FiltrosAusentes é setada.
        FiltrosAusentes = true;
        // E o loop é abandonado.
        break;
      }
      else
        // Por outro lado, se tivermos valor definido, o filtro é processado e adicionado ao array FiltrosProcessados.
        FiltrosProcessados.push(Filtros[i][0]+"="+Valor);
    }
    // Vamos agora checar a flag FiltrosAusentes.
    if(FiltrosAusentes)
    {
      // Se ela for true, significa que um ou mais filtros estão faltando. Neste caso, o combo não pode ser preenchido.
      // Vamos apenas esvaziar o listbox, preencher o textbox com uma mensagem explicando o ocorrido e torná-lo inativo.
      this.ElementoLista.options.length = 0;
      OcultaElemento(this.ElementoLista);
      this.ElementoTexto.text = GLFiltroAusente;
      this.ElementoTexto.disabled = true;
    }
    else
    {
      // Com todos os filtros prontos, podemos dar continuidade na chamada AJAX. É hora de exibir a imagem de espera.
      ExibeElemento(this.ElementoImagem);
      // Criamos uma referência ao objeto atual, para que o callback possa manipulá-lo.
      Objeto = this;
      */
      if(!Ordem) Ordem = '';
      if(!Pagina) Pagina = 1;
      if(!NumRegistrosPagina) NumRegistrosPagina = GLNumRegistrosPagina;

      this.FiltrosProcessados = new Array();

      // Criamos uma referência ao objeto atual, para que o callback possa manipulá-lo.

      // E finalmente a chamada AJAX é feita, com a passagem da URL que vai retornar o XML desejado, 
      // e o callback que vai processá-lo.
      this.Ajax = new MVXAjax();
      this.Ajax.AcionaAjax("xml?a=5&t="+this.Tabela+"&n="+Pagina+"&r="+NumRegistrosPagina+"&o="+Ordem+"&f="+escape(this.FiltrosProcessados.join(" and ")),
        function(XMLDoc) 
        {
          // Vamos checar se houve retorno.
          if(XMLDoc.hasChildNodes())
          { 
            // Vamos obter o nome do campo PK.
            this.DadosEstruturais = XMLDoc.getElementsByTagName('dados')[0].childNodes;
            this.PK = this.DadosEstruturais.item(2).childNodes[0].nodeValue;
            // Se sim, vamos checar quantos registros vieram.
            this.Registros = XMLDoc.getElementsByTagName('valores')[0].childNodes;
            this.Campos = XMLDoc.getElementsByTagName('campos')[0].childNodes;
            this.NumRegistros = this.Registros.length;
            this.NumCampos = this.Campos.length;
            if(this.NumRegistros > 0)
            {
              this.Linha = null;
              this.Coluna = null;
              this.AtributoEstilo = null;
              this.Comando = null;
              this.URL = null;
              this.Cabecalho = null;
              this.NomeCampo = null;

              this.DataGrid = document.createElement("table");
              this.DataGrid.id = this.ID;
              this.AtributoEstilo = document.createAttribute("class");
              this.AtributoEstilo.nodeValue = this.Estilo;
              this.DataGrid.setAttributeNode(this.AtributoEstilo);
              // Agora vamos adicionar a linha de header do grid. Faremos um loop pelos nós de campos do XML.
              this.Linha = this.DataGrid.appendChild(document.createElement("tr"));
              this.AtributoEstilo = document.createAttribute("class");
              this.AtributoEstilo.nodeValue="Titulo";
              this.Linha.setAttributeNode(this.AtributoEstilo);
              // Antes do loop, vamos inserir uma coluna para os comandos.
              this.Coluna = this.Linha.appendChild(document.createElement("td"));
              for(var i = 0; i<this.NumCampos; i++)
              {
                this.Coluna = this.Linha.appendChild(document.createElement("td"));
                this.NomeCampo = this.Campos[i].nodeName;
                this.AtributoEstilo = document.createAttribute("class");
                this.AtributoEstilo.nodeValue = this.NomeCampo;
                this.Coluna.setAttributeNode(this.AtributoEstilo);
                this.Cabecalho = this.Coluna.appendChild(document.createElement("a"));
                this.SentidoOrdem = null;
                if(Ordem.substring(2)==this.NomeCampo && Ordem.substring(0, 2)=='A_') this.SentidoOrdem = 'D_'; else this.SentidoOrdem = 'A_';
                var obj = this;
                this.FuncaoClick = function() {alert(obj.Nome);obj.Popula(this.SentidoOrdem+this.NomeCampo);};
                
                //this.FuncaoClick = new Function('', 'alert(obj); obj.Popula("'+this.SentidoOrdem+this.NomeCampo+'");');
                AdicionaEvento(this.Cabecalho, 'click', this.FuncaoClick);
                
                //AdicionaEvento(this.Cabecalho, 'click', new Function('', 'Popula("'+this.SentidoOrdem+this.NomeCampo+'");'));
                this.Cabecalho.appendChild(document.createTextNode(this.Campos[i].childNodes[0].childNodes[0].nodeValue));
              }
              // Agora vem o loop que vai adicionar os elementos encontrados ao listbox.
              for(var i = 0; i<this.NumRegistros; i++)
              {
                this.Linha = this.DataGrid.appendChild(document.createElement("tr"));
                this.AtributoEstilo = document.createAttribute("class");
                this.AtributoEstilo.nodeValue="Item"+i%2;
                this.Linha.setAttributeNode(this.AtributoEstilo);
                // Antes do loop pelos campos, adicionaremos a célula de comandos. Os comandos estão no array informado na criação do this.
                this.Coluna = this.Linha.appendChild(document.createElement("td"));
                this.AtributoEstilo = document.createAttribute("class");
                this.AtributoEstilo.nodeValue = "Comandos";
                this.Coluna.setAttributeNode(this.AtributoEstilo); 
                this.NumComandos = this.Comandos.length;
                for(var j = 0; j<this.NumComandos; j++)
                {
                  this.SpanComando = this.Coluna.appendChild(document.createElement("span"));
                  this.Comando = this.SpanComando.appendChild(document.createElement("a"));
                  this.URL = document.createAttribute("href");
                  this.URL.nodeValue = str_replace(['%%%[PK]'], [this.Registros[i].lastChild.childNodes[0].nodeValue], this.Comandos[j][1]);
                  this.Comando.setAttributeNode(this.URL);
                  this.Comando.appendChild(document.createTextNode(this.Comandos[j][0]));
                }
                // Agora vamos adicionar os dados.
                for(var j = 0; j<this.NumCampos; j++)
                {
                  this.Coluna = this.Linha.appendChild(document.createElement("td"));
                  if(this.Registros[i].childNodes[j].hasChildNodes()) 
                  {
                    this.AtributoEstilo = document.createAttribute("class");
                    this.AtributoEstilo.nodeValue = this.Registros[i].childNodes[j].nodeName;
                    this.Coluna.setAttributeNode(this.AtributoEstilo); 
                    this.Coluna.appendChild(document.createTextNode(this.Registros[i].childNodes[j].childNodes[0].nodeValue));
                  }
                }
              }
            }

            // Agora vamos criar a barra de navegação.

            // E agora vamos adicionar o controle. Vamos começar checando se ele já existe. 
            
            //this.DataGrid = document.createTextNode(XMLDoc);
            //alert("Objeto ID: "+this.ID);
            this.Elemento = document.getElementById(this.ID);
            //alert("Elemento: "+this.Elemento);
            if(this.Elemento)
              // Se ele já existe, vamos substituir seu conteúdo. Se não existe, vamos criá-lo.
              document.getElementById(this.Container).replaceChild(this.DataGrid, this.Elemento);
            else
              document.getElementById(this.Container).appendChild(this.DataGrid);
           
          }

        }, this
      );

  }
}

