Una GridView con supporto per più righe selezionabili

di Marco Leoncini, in ASP.NET 2.0, Custom Control, GridView,

Il controllo GridView non offre alcun tipo di supporto per la selezione multipla delle righe e del valore relativo a uno dei campi chiave.
Il classico workaround consiste nel creare una TemplateColumn definendo un ItemTemplate con almeno una CheckBox, così che ad ogni PostBack iterando le righe del gridview venga recuperato il valore del campo chiave in base allo stato della checkbox.

Renderemo questa soluzione riutilizzabile e facilmente manutenibile creando un custom Web Control e faremo inoltre in modo di mantenere le selezioni tra le operazioni di Sorting e Paging della griglia.

Per prima cosa creiamo una nuova classe chiamata CheckField, ereditando direttamente da DataControlField, al fine di sfruttare questa classe come ogni altro campo.

L'implementazione è semplice e consiste nell'override del metodo InizializeCell, al fine di istanziare la CheckBox e aggiungerla alla collezione Controls della cella.

public override void InitializeCell(DataControlFieldCell cell, DataControlCellType cellType, DataControlRowState rowState, int rowIndex)
{
  base.InitializeCell(cell, cellType, rowState, rowIndex);

  if(cellType == DataControlCellType.DataCell)
  {
      
      CheckBox _checkBox = new CheckBox();

     cell.Controls.Add(_checkBox);
  }
}

Il passo successivo è creare la GridView custom, definendo due nuove proprietà: SelectedDataValues e DataValueIndex. Quest'ultima ha lo scopo di definire l'indice del valore del campo chiave che per ogni riga selezionata che aggiungeremo alla collezione di SelectedDataValues.

public int DataValueIndex
{
  get { return _dataValueIndex; }
  set
  {
    if (!DesignMode)
    {
      if (value < 0 || value > DataKeyNames.Length)
        throw new ArgumentOutOfRangeException("DataValueIndex");

        _dataValueIndex = value;
        SelectedDataValues.Clear();
    }
  }
}

public ArrayList SelectedDataValues
{
  get
  {
    if (_selectedDataKeyValueArrayList == null)
    {
        _selectedDataKeyValueArrayList = new ArrayList();
    }
    return _selectedDataKeyValueArrayList;
  }
}

Eseguiamo l'override del metodo CreateColumns per istanziare un nuovo oggetto di tipo CheckField e aggiungerlo alla collezione delle colonne già esistenti, così da fornire l'interfaccia per la selezione multipla.

protected override ICollection CreateColumns(PagedDataSource dataSource, bool useDataSource)
{
  ArrayList _collection = base.CreateColumns(dataSource, useDataSource) as ArrayList;

  if (_collection != null)
  {
        _collection.Add(new CheckField());

       _checkBoxIndex = _collection.Count - 1;

  }

  return _collection;
}

Occupiamoci adesso di recuperare per ogni riga lo stato della CheckBox e nel caso quest'ultima sia selezionata aggiungeremo il valore del campo chiave nella collezione SelectedDataValues, allo scopo eseguiamo l'ovveride del metodo OnLoad.

protected override void OnLoad(EventArgs e)
{
  base.OnLoad(e);

  if (IsMultyPageCapable)
  {
      foreach (GridViewRow row in Rows)
      {
          CheckBox c = RetriveRowCheckBox(row);

          object _dataKeyValue = DataKeys[row.RowIndex].Values[DataValueIndex];

          bool _conteinValue = SelectedDataValues.Contains(_dataKeyValue);

          if (c.Checked)
          {
            if (!_conteinValue)
            {
              SelectedDataValues.Add(_dataKeyValue);
            }
          }
          else
          { 
            if (_conteinValue)
            {
              SelectedDataValues.Remove(_dataKeyValue);
            }
          }
      }
  }
}

Infine eseguiamo l'override del metodo OnPreRender per impostare lo stato delle CheckBox in base ai valori selezionati in precedenza.

protected override void OnPreRender(EventArgs e)
{
  base.OnPreRender(e);

  if (IsMultyPageCapable)
  {
      foreach (GridViewRow row in Rows)
      {
          
          CheckBox c = RetriveRowCheckBox(row);

          object _dataKeyValue = DataKeys[row.RowIndex].Values[DataValueIndex];

          
          if (SelectedDataValues.Contains(_dataKeyValue))
          {
            c.Checked = true;
          }
      }
  }
}

Cicliamo ogni riga del GridView, se il valore del campo chiave è presente nella collezione SelectedDataValues selezioneremo la CheckBox, così facendo manterremo la selezione tra operazioni di Sorting, Paging, al costo però di eseguire inutilmente l'operazione nel caso in cui il PostBack non sia eseguito dal GridView stesso.

Allo script è allegato il codice completo e commentato in ogni passaggio.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi