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