LA.Net
Reflexões sobre C#, .Net e programação em geral

Nos últimos tempos tenho dedicado algum do meu tempo livre a expandir as funcionalidades da GridView. Antes de tornar o controlo público, queria que este permitisse a selecção de vários elementos (leia-se linhas) sem efectuar um postback completo da página. No meu último artigo apresentei uma primeira versão deste controlo em que já era possível efectuar a inserção de novos registos. A alteração do controlo por forma a que seja possível seleccionar várias linhas também não foi muito complicada: ao fim de 2 horas estava concluído o processo.

Contudo, achei que não deveria publicar o controlo sem que fosse possível efectuar a selecção de vários itens sem efectuar o postback da página. Nos últimos tempos tenho tentado configurar o controlo de forma a que seja possível utilizar esta funcionalidade. Infelizmente não consegui construir o controlo correctamente. Após algumas horas de frustração, consegui seleccionar as linhas, mas ao efectuar um postback completo deparei-me com a corrupção do ViewState. Apesar de todos os meus esforços, não consegui resolver este problema. Como não vou ter mais tempo para me debruçar sobre este controlo, resolvi publicá-lo assim (portanto, sem conseguir colocar as funcionalidades relativas ao callback a funcionar a 100%). Só me resta esperar que alguém com mais capacidades do que eu tenha algum interesse pela questão e consiga descobrir o porquê da corrupção do ViewState.

De qualquer forma, fica o consolo de ter construído um controlo que permite a selecção de vários elementos e a introdução de novos registos (ainda que apenas funcione correctamente em modo de postback...)

Enquanto não terminar a escrita do artigo que documenta a construção da LAGridView, achei por bem fornecer algumas informações sobre o controlo. A necessidade de construção deste controlo deveu-se ao facto de querer (começar a) efectuar o port de controlos actuais para a nova versão da framework.

Bom, mas hoje decidi falar sobre o que falhou na construção deste controlo. O grande problema da utilização deste controlo resume-se ao facto de ter decidido adicionar uma nova coluna à grid que contém apenas uma checkbox e que permite ao utilizar seleccionar uma linha. Uma vez que queria utilizar a grid em ambientes de binding, não podia utilizar a CheckBoxField para efectuar essa operação. Então o primeiro passo consistiu em definir um novo tipo de coluna (apropriadamente designado de LACheckBoxField) cuja principal função é adicionar à célula uma checkbox que iria despoletar o processo de selecção de uma linha.

A implementação desta classe foi muito simples. De facto, o código é tão simples que vou acabar por reproduzi-lo aqui:

public class LACheckBoxField : DataControlField
{
  #region Properties
    public string Key
    {
      get
      {
        return ViewState ["Key"] == null ? "CheckKey" : ViewState ["Key"].ToString( );
      }
      set
      {
        ViewState ["Key"] = value;
      }
     }
   #endregion
   #region overrides
    public override void ExtractValuesFromCell( IOrderedDictionary dictionary, 
         DataControlFieldCell cell, DataControlRowState rowState, bool includeReadOnly )
    {
      Control ctl = null;
      object ret = null;
      if ( cell.Controls.Count > 0 )
      {
        ctl = cell.Controls [0];
        CheckBox chk = ctl as CheckBox;
        if ( chk != null && ( includeReadOnly || chk.Enabled ) )
           ret = chk.Checked;
       }
       if ( ret == null )
         return;
       if ( dictionary.Contains( this.Key ) )
           dictionary [this.Key] = ret;
       else
           dictionary.Add( this.Key, ret );
    }
        
    public override void InitializeCell( DataControlFieldCell cell,   
      DataControlCellType cellType, DataControlRowState rowState, int rowIndex )
    {
       base.InitializeCell( cell, cellType, rowState, rowIndex );
       if ( cellType == DataControlCellType.DataCell )
       {
          CheckBox chk = new CheckBox( );
          cell.Controls.Add( chk );
       }
     }
     
     public override void ValidateSupportsCallback()
     {
     }
    #endregion
}

 

Existem alguns pormenores a reter:

  • O método InitializeCell inicializa a célula adicionando-lhe a CheckBox no seu interior.
  • O método ExtractValuesFromCell irá ser evocado quando for necessário obter o valor contido na célula. Neste caso, o valor será true ou false (consoante a CheckBx esteja ou não seleccionada)
  • O override do método ValidateSupportsCallback destina-se apenas a permitir a utilização deste mecanismo (por defeito a classe base - DataControlField - gera uma excepção no interior deste método de forma a indicar que não deve ser utilizada em callback).

A adição desta coluna à grid é efectuada durante o evento Init.Bom, acabei de aperceber-me que este post já vai longo pelo que amanhã vou fornecer mais detalhes relativos à construção deste controlo

posted on Thursday, December 30, 2004 12:24 AM
Comments
No comments posted yet
Title  
Name  
Url
Box Code
Protected by FormShield
Comments