Em determinadas situações precisamos percorrer os registros do GridView, um a um, sem utilizar a paginação do próprio que engloba grupos de páginas. Uma maneira de se fazer isso é utilizar botões para avançar, retroceder, ir ao primeiro e ao último registro da página.

Para resolver isso podemos criar uma variável que será uma lista genérica, que ficará no ViewState, recuperar os dados que queremos consultar, jogarmos os mesmos nesta lista e a utilizarmos em cada um dos botões citados acima. Se você não conhece o ViewState sugiro que veja estes artigos.

A Listagem 01 ilustra a criação da variável citada anteriormente.


public List<Products> listaProdutos
{
get
{
    if (ViewState["vwListaProdutos"] != null)
        return (List<Products>)ViewState["vwListaProdutos"];
    else
        return null;
}
set
{
    ViewState["vwListaProdutos"] = value;
}
 }
Listagem 01 – Lista armazenada no ViewState

No exemplo uso uma lista genérica da classe Products, referente à tabela de mesmo nome do banco Northwind. A classe está ilustrada na Listagem 02.


[Serializable]
    public class Products
{
    public int ProductID { get; set; }
    public string ProductName { get; set; }
    public decimal UnitPrice { get; set; }
}
Listagem 02Classe Products

Note que a classe tem, acima dela, a marcação que ela é uma classe do tipo Serializable (serializável), o que significa que estamos mantendo o estado do objeto/classe para o utilizarmos posteriormente em nosso desenvolvimento.

Mais informações sobre serialização: Serializando Objetos em NET

A Listagem 03 ilustra a declaração de uma variável do tipo int, no ViewState. Ela será usada na codificação dos botões.


public Int32 indiceLinha
{
    get
    {
        if (ViewState["vwIndiceLinha"] != null)
            return (Int32)ViewState["vwIndiceLinha"];
        else
            return Int32.MinValue;
    }
    set
    {
        ViewState["vwIndiceLinha"] = value;
    }
}
Listagem 03 – Índice da linha, armazenado no ViewState

Neste exemplo estou utilizando apenas dois campos, ProductName e UnitPrice. Assim, a Figura 01 ilustra a minha aspx com os botões que iremos usar para navegar entre os registros.

img
Figura 01 – Aparência da página de exemplo

Tendo em vista que já temos pronto o método para carregar os dados no GridView e o mesmo já está carregado com os dados, codifique os botões, como ilustram as Listagens 04, 05, 06 e 07.


protected void btnPrimeiro_Click(object sender, EventArgs e)

{

    if (listaProdutos != null)

    {

        var primeiroRegistro = listaProdutos.First();

        this.txtProduto.Text = primeiroRegistro.ProductName;

        this.txtPrecoUnitario.Text = primeiroRegistro.UnitPrice.ToString();



        if (indiceLinha > Int32.MinValue)

            this.grdDados.Rows[indiceLinha].Style.Clear();



        this.grdDados.Rows[0].Style.Add("background-color", "lightgray");

        indiceLinha = 0;

    }

}
Listagem 04 – Primeiro Registro

protected void btnUltimo_Click(object sender, EventArgs e)
{
    if (listaProdutos != null)
    {
        var primeiroRegistro = listaProdutos.Last();
        this.txtProduto.Text = primeiroRegistro.ProductName;
        this.txtPrecoUnitario.Text = primeiroRegistro.UnitPrice.ToString();

        if (indiceLinha > Int32.MinValue)
            this.grdDados.Rows[indiceLinha].Style.Clear();

        this.grdDados.Rows[listaProdutos.Count - 1].Style.Add("background-color", "lightgray");
        indiceLinha = listaProdutos.Count - 1;
    }
}
Listagem 05 – Último Registro

protected void btnProximo_Click(object sender, EventArgs e)
{
    if (listaProdutos != null)
    {
        for (int i = 0; i < listaProdutos.Count; i++)
        {
            if (indiceLinha == i && indiceLinha < listaProdutos.Count - 1)
                {
                i++;
                var proximoRegistro = listaProdutos[i];
                this.txtProduto.Text = proximoRegistro.ProductName;
                this.txtPrecoUnitario.Text = proximoRegistro.UnitPrice.ToString();
                this.grdDados.Rows[i - 1].Style.Clear();
                this.grdDados.Rows[i].Style.Add("background-color", "lightgray");
                indiceLinha = i;  
            }
        }
    }
}
Listagem 06 – Próximo Registro

protected void btnAnterior_Click(object sender, EventArgs e)
{
    if (listaProdutos != null)
    {
        for (int i = 0; i < listaProdutos.Count; i++)
        {
            if (indiceLinha > 0 && indiceLinha == i)
            {
                i--;
                var proximoRegistro = listaProdutos[i];
                this.txtProduto.Text = proximoRegistro.ProductName;
                this.txtPrecoUnitario.Text = proximoRegistro.UnitPrice.ToString();
                this.grdDados.Rows[i + 1].Style.Clear();
                this.grdDados.Rows[i].Style.Add("background-color", "lightgray");
                indiceLinha = i;
            }
        }
    }
}
Listagem 07 – Registro Anterior

Note que as Listagens 04 e 05 são bem parecidas, assim como a 06 e 07 se parecem. Na Listagem 04 uso o método First(), que me retorna o primeiro registro da lista de dados, assim fica bem simples para popular os campos e pintar o GridView. Faço o mesmo na Listagem 05 com o método Last().

Nas Listagens 06 e 07 uso um laço for para verificar em que linha o usuário passou por último (daí a importância da variável declarada na Listagem 03). Dependendo do botão eu incremento ou decremento o valor de i, que é usado para pintar a linha do registro selecionado.

Não sei se a codificação usada nas Listagens 06 e 07 são as melhores (entenda-se as menores!), mais são as que, pelo menos pra mim, funcionam. Caso tenham soluções melhores postem nos comentários deste artigo, gostaria de aprendê-las. O resultado dos testes com os botões estão ilustrados nas Figuras 02, 03, 04 e 05.

img
Figura 02 – Primeiro Registro
img
Figura 03 – Último Registro
img
Figura 04 – Registro Anterior