Jasinski Technical Wiki

Navigation

Home Page
Index
All Pages

Quick Search
»
Advanced Search »

Contributor Links

Create a new Page
Administration
File Management
Login/Logout
Your Profile

Other Wiki Sections

Software

PoweredBy

GridViewExtender Class - ASP.NET

RSS
Modified on Tue, Sep 15, 2009, 12:06 PM by Administrator Categorized as ASP·NET Web Forms, Class Library
This class is superseded by the GridView class.

Table of Contents [Hide/Show]


   Features
   Consuming the Class in Your ASPX Page
      ASPX Markup Code
      Declare a Private Variable
         C#
         Visual Basic
      Write Callback Function to Retrieve Data
         C#
         Visual Basic
      Write Callback Function to Save Changes to a Row
         C#
         Visual Basic
      Write Callback Function to Delete a Row
         C#
         Visual Basic
      Instantiate the Class
         C#
         Visual Basic
      Querying Data
   Source Code
      Sample Code-Behind
         C#
         Visual Basic
      GridViewExtender Class
         C#
         Visual Basic

{outline||<1> - |

.<1> - }

Features

The GridViewExtender class provides the following features.

  • Client-side confirmation (via a JavaScript confirm dialog) before deleting a row from the grid.
  • Callback functions may be specified for the data binding, saving, and deleting functions. These are specified when the class is instantiated. This allows the developer to focus on the data-processing and business logic of the grid, rather than the proper "wiring" of the event handlers.
  • Automatic display of the correct action buttons depending on whether a row is being editted or not, the same as how the default action buttons are displayed.

Consuming the Class in Your ASPX Page

ASPX Markup Code

The following markup code is only a partial listing. You must add your own columns for the data fields. The key element here is the the <asp:TemplateField> that contains the action buttons, because the GridViewExtender class expects it to be coded this way.

  • You can change the order of the buttons, or even move them to different columns.
  • You can change the ImageUrl for each button.
  • If you want to use LinkButtons or Buttons instead of ImageButtons, you must change the code in the GridViewExtender class accordingly. Search for "ImageButton" and replace it with either "LinkButton" or "Button" according to the button style you decide to use.

<asp:GridView runat="server" ID="uxGridView" AutoGenerateColumns="false"
    CellPadding="3" CellSpacing="0" DataKeyNames="ID">

    <EmptyDataTemplate>
        No records match your search criteria.
    </EmptyDataTemplate>

    <Columns>

        <%-- TODO: Add columns to this GridView --%>

        <asp:TemplateField>
                            
            <HeaderTemplate>Action</HeaderTemplate>
                                
            <ItemTemplate>
                                
                <asp:ImageButton runat="server" ID="uxEditButton"
                    CommandName="Edit" ImageUrl="~/images/Pencil.png" 
                    ToolTip="Edit"
                    />
                                        
                <asp:ImageButton runat="server" ID="uxDeleteButton"
                    CommandName="Delete" ImageUrl="~/images/Delete.png" 
                    ToolTip="Delete" 
                    />
                
                <%-- TODO: Specify ValidationGroup for the Save button --%>
 
                <asp:ImageButton runat="server" ID="uxSaveButton"
                    CommandName="Update" ImageUrl="~/images/Save.png" 
                    ToolTip="Save Changes" 
                    />
                                        
                <asp:ImageButton runat="server" ID="uxCancelButton"
                    CommandName="Cancel" ImageUrl="~/images/StopSign.png" 
                    ToolTip="Discard Changes"
                    />
                                
            </ItemTemplate>
                            
        </asp:TemplateField>


    </Columns>


</asp:GridView>

<asp:Button runat="server" ID="uxAddNewButton" Text="Add New" />

Declare a Private Variable

C#

private GridViewExtender _gridViewExt;

Visual Basic

Private _gridViewExt as GridViewExtender

Write Callback Function to Retrieve Data

This will be the Requery Handler procedure used when you instantiate the GridViewExtender class. Its purpose is to retrieve data to be displayed in the grid. Make sure you use the function signature shown in the example.

C#

private DataTable QueryData()
{
    int id = Session["ID"];
    DataTable t = db.GetRecords(id);
    return t;
} 

Visual Basic

Private Function QueryData() As DataTable

    Dim id as Integer = Session("ID")
    Dim t as DataTable = db.GetRecords(id)
    Return t

End Function

Write Callback Function to Save Changes to a Row

This will be the Update Handler procedure used when you instantiate the GridViewExtender class. Its purpose is to save the user's changes to the edited row. Make sure you use the function signature shown in the example.

C#

private void UpdateData(DataKey rowKey, GridViewRow gvRow)
{
    if (Page.IsValid)
    {
        int id = int.Parse(rowKey["ID"].ToString());
        string description = (gvRow.FindControl("uxDescriptionTextBox") as TextBox).Text;
        db.SaveData(id, description);
    }
} 

Visual Basic

Private Sub UpdateData(ByVal rowKey as DataKey, ByVal gvRow as GridViewRow)

    If Page.IsValid Then

        Dim id as Integer = Convert.ToInt32(rowKey("ID"))
        Dim description As String = CType(gvRow.FindControl("uxDescriptionTextBox"), TextBox).Text
        db.SaveData(id, description)

    End If

End Sub

Write Callback Function to Delete a Row

This will be the Delete Handler procedure used when you instantiate the GridViewExtender class. Its purpose is to delete the selected row. Make sure you use the function signature shown in the example.

C#

private void DeleteData(DataKey rowKey)
{
    int id = int.Parse(rowKey["ID"].ToString());
    db.DeleteData(id);
} 

Visual Basic

Private Sub DeleteData(ByVal rowKey as DataKey)

    Dim id as Integer = Convert.ToInt32(rowKey("ID"))
    db.DeleteData(id)

End Sub

Instantiate the Class

This should be done unconditionally (i.e., NOT inside the If Not Page.IsPostBack block).

C#

_gridViewExt = new GridViewExtender(uxGridView, "Description", 
                   New EmptyDelegate(AddressOf QueryData), 
                   New DataKeyDelegate(AddressOf DeleteData), 
                   New GridViewRowDelegate(AddressOf UpdateData));

Visual Basic

_gridViewExt = new GridViewExtender(uxGridView, "Description", _
                   New EmptyDelegate(AddressOf QueryData), _
                   New DataKeyDelegate(AddressOf DeleteData), _
                   New GridViewRowDelegate(AddressOf UpdateData))

Querying Data

This should be done conditionally (i.e., inside the If Not Page.IsPostBack block).

_gridViewExt.Requery()

Source Code

Sample Code-Behind

C#

private GridViewExtender _gridViewExt; 

protected void Page_Load(object sender, EventArgs e)
{
    _gridViewExt = New GridViewExtender(uxGridView, "Description", 
                       New EmptyDelegate(AddressOf QueryData), 
                       New DataKeyDelegate(AddressOf DeleteData), 
                       New GridViewRowDelegate(AddressOf UpdateData));

    if (!Page.IsPostBack)

        _gridViewExt.Requery();

}
private DataTable QueryData()
{
    //TODO: Code the QueryData procedure
    //int id = Session["ID"];
    //DataTable t = db.GetRecords(id);
    //return t;
}

private void UpdateData(DataKey rowKey, GridViewRow gvRow)
{
    //TODO: Code the UpdateData procedure
    if (Page.IsValid)
    {
        //int id = int.Parse(rowKey["ID"]);
        //string description = (gvRow.FindControl("uxDescriptionTextBox") As TextBox).Text;
        //db.SaveData(id, description);
    }
}
private void DeleteData(DataKey rowKey)
{
    //TODO: Code the DeleteData procedure
    //int id = int.Parse(rowKey["ID"]);
    //db.DeleteData(id);
}
private void uxAddNewButton_Click(object sender, EventArgs e)
{
    _gridViewExt.AddNew();
}

Visual Basic

Private _gridViewExt As GridViewExtender

Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load

    _gridViewExt = New GridViewExtender(uxGridView, "Description", _
                       New EmptyDelegate(AddressOf QueryData), _
                       New DataKeyDelegate(AddressOf DeleteData), _
                       New GridViewRowDelegate(AddressOf UpdateData))

    If Not Page.IsPostBack Then

        _gridViewExt.Requery()

    End If

End Sub

Private Function QueryData() As DataTable

    'TODO: Code the QueryData procedure
    'Dim id as Integer = Session("ID")
    'Dim t as DataTable = db.GetRecords(id)
    'Return t

End Function

Private Sub UpdateData(ByVal rowKey as DataKey, ByVal gvRow as GridViewRow)

    'TODO: Code the UpdateData procedure
    If Page.IsValid Then

        'Dim id as Integer = Convert.ToInt32(rowKey("ID"))
        'Dim description As String = CType(gvRow.FindControl("uxDescriptionTextBox"), TextBox).Text
        'db.SaveData(id, description)

    End If

End Sub

Private Sub DeleteData(ByVal rowKey as DataKey)

    'TODO: Code the DeleteData procedure
    'Dim id as Integer = Convert.ToInt32(rowKey("ID"))
    'db.DeleteData(id)

End Sub

Private Sub uxAddNewButton_Click(ByVal sender As Object, ByVal e As EventArgs) Handles uxAddNewButton.Click

    _gridViewExt.AddNew()

End Sub

GridViewExtender Class

C#

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data;

public delegate DataTable EmptyDelegate();
public delegate void DataKeyDelegate(DataKey rowKey);
public delegate void GridViewRowDelegate(DataKey rowKey, GridViewRow gvRow);

public class GridViewExtender
{
    private GridView _gridView;
    private string _identifyingField;
    private EmptyDelegate _requeryHandler;
    private DataKeyDelegate _deleteHandler;
    private GridViewRowDelegate _updateHandler;

    //- Constructor -------------------------------------------------------------------------------
    public GridViewExtender(GridView gridView, string identifyingField, EmptyDelegate 
        requeryHandler, DataKeyDelegate deleteHandler, GridViewRowDelegate updateHandler)
    {
        _gridView = gridView;
        _identifyingField = identifyingField;
        _requeryHandler = requeryHandler;
        _deleteHandler = deleteHandler;
        _updateHandler = updateHandler;

        _gridView.RowDataBound 
            += new GridViewRowEventHandler(_gridView_RowDataBound);

        _gridView.RowEditing
            += new GridViewEditEventHandler(_gridView_RowEditing);

        _gridView.RowCancelingEdit 
            += new GridViewCancelEditEventHandler(_gridView_RowCancelingEdit);

        _gridView.RowDeleting 
            += new GridViewDeleteEventHandler(_gridView_RowDeleting);

        _gridView.RowUpdating 
            += new GridViewUpdateEventHandler(_gridView_RowUpdating);
    }


    //- Public Methods ----------------------------------------------------------------------------
    public void AddNew()
    {
        BindToDataTable(-1, true);
    }
    //---------------------------------------------------------------------------------------------
    public void Requery()
    {
        this.EditIndex = this.EditIndex;
    }
    //---------------------------------------------------------------------------------------------
    public bool TryGetDataRow(GridViewRow row, DataRow dataRow)
    {
        bool result = false;

        DataRowView drv = row.DataItem as DataRowView;

        if (drv != null)
        {
            dataRow = drv.Row;
            result = (dataRow != null);
        }

        return result;
    }

    //- Private Methods ---------------------------------------------------------------------------
    private void BindToDataTable(int editIndex)
    {
        BindToDataTable(editIndex, false);
    }
    //---------------------------------------------------------------------------------------------
    private void BindToDataTable(int editIndex, bool addNew)
    {
        _gridView.EditIndex = editIndex;

        if (_requeryHandler != null)
        {
            DataTable t = _requeryHandler();

            if (addNew)
            {
                foreach (DataColumn col in t.Columns)
                    col.AllowDBNull = true;

                DataRow newRow = t.NewRow();
                t.Rows.Add(newRow);
            }

            _gridView.DataSource = t;

            if (addNew)
                _gridView.EditIndex = t.Rows.Count - 1;

            _gridView.DataBind();

            foreach (GridViewRow row in _gridView.Rows)
            {
                if (row.RowType != DataControlRowType.DataRow)
                {
                    SetVisibility(row, "uxDeleteButton", false);
                    SetVisibility(row, "uxEditButton", false);
                    SetVisibility(row, "uxSaveButton", false);
                    SetVisibility(row, "uxCancelButton", false);
                }
                else
                {
                    bool editMode = (row.RowIndex == _gridView.EditIndex); 

                    SetVisibility(row, "uxDeleteButton", !editMode);
                    SetVisibility(row, "uxEditButton", !editMode);
                    SetVisibility(row, "uxSaveButton", editMode);
                    SetVisibility(row, "uxCancelButton", editMode);
                }
            }
        }
    }
    //---------------------------------------------------------------------------------------------
    private int EditIndex
    {
        get { return _gridView.EditIndex; }
        set { BindToDataTable(value); }
    }

    //- Event Handlers ----------------------------------------------------------------------------
    private void _gridView_RowDataBound(object sender, GridViewRowEventArgs e)
    {
        try
        {
            if (e.Row != null && e.Row.RowType == DataControlRowType.DataRow && 
                e.Row.DataItem != null)
            {
                DataRow dataRow = (e.Row.DataItem as DataRowView).Row;

                if (dataRow != null && dataRow[_identifyingField] != null)
                {
                    string identifier = dataRow[_identifyingField].ToString();
                    WebControl control = e.Row.FindControl("uxDeleteButton") as WebControl;
                    ImageButton button = null;

                    if (control != null)
                    {
                        button = control as ImageButton;
                        button.OnClientClick = "confirm('Delete [" + identifier.Replace("'", "\\'") 
                                                    + "]?')'";
                    }

                }
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    //---------------------------------------------------------------------------------------------
    private void _gridView_RowEditing(object sender, GridViewEditEventArgs e)
    {
        BindToDataTable(e.NewEditIndex);
    }
    //---------------------------------------------------------------------------------------------
    private void _gridView_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)
    {
        BindToDataTable(-1);
    }
    //---------------------------------------------------------------------------------------------
    private void _gridView_RowDeleting(object sender, GridViewDeleteEventArgs e)
    {
        if (_deleteHandler != null & _requeryHandler != null)
        {
            try
            {
                _deleteHandler(_gridView.DataKeys[e.RowIndex]);
                BindToDataTable(-1);
            }
            catch //(Exception ex)
            {
                e.Cancel = true;
            }
        }
    }
    //---------------------------------------------------------------------------------------------
    private void _gridView_RowUpdating(object sender, GridViewUpdateEventArgs e)
    {
        if (_updateHandler != null & _requeryHandler != null)
        {
            try
            {
                _updateHandler(_gridView.DataKeys[e.RowIndex], _gridView.Rows[e.RowIndex]);
                BindToDataTable(-1);
            }
            catch
            {
                e.Cancel = true;
            }
        }
    }

    //- Helper Functions --------------------------------------------------------------------------
    private static void SetVisibility(GridViewRow row, string controlName, bool visible)
    {
        WebControl control = row.FindControl(controlName) as WebControl;

        if (control != null)
            control.Visible = visible;
    }

}

Visual Basic

Imports Microsoft.VisualBasic
Imports System.Data

Public Delegate Function EmptyDelegate() As DataTable
Public Delegate Sub DataKeyDelegate(ByVal rowKey As DataKey)
Public Delegate Sub GridViewRowDelegate(ByVal rowKey As DataKey, ByVal gvRow As GridViewRow)

Public Class GridViewExtender

    Private WithEvents _gridView As GridView
    Private _identifyingField As String
    Private _requeryHandler As EmptyDelegate
    Private _deleteHandler As DataKeyDelegate
    Private _updateHandler As GridViewRowDelegate

    '-- Constructor -------------------------------------------------------------------------------
    Public Sub New(ByVal gridView As GridView, ByVal identifyingField As String, ByVal _
    requeryHandler As EmptyDelegate, ByVal deleteHandler As DataKeyDelegate, ByVal updateHandler As _
    GridViewRowDelegate)

        _gridView = gridView
        _identifyingField = identifyingField
        _requeryHandler = requeryHandler
        _deleteHandler = deleteHandler
        _updateHandler = updateHandler

    End Sub

    '-- Public Methods ----------------------------------------------------------------------------
    Public Sub AddNew()
        BindToDataTable(-1, True)
    End Sub

    '----------------------------------------------------------------------------------------------
    ''' <summary>
    ''' Gets or sets the EditIndex of the grid.  After setting the EditIndex, requeries the grid.
    ''' </summary>
    ''' <value>Specify -1 to have no row in edit mode.</value>
    Public Property EditIndex() As Integer
        Get
            Return _gridView.EditIndex
        End Get
        Set(ByVal value As Integer)
            BindToDataTable(value)
        End Set
    End Property

    '----------------------------------------------------------------------------------------------
    Public Sub Requery()
        Me.EditIndex = Me.EditIndex
    End Sub

    '-- Private Methods ---------------------------------------------------------------------------
    Private Sub BindToDataTable(ByVal editIndex As Integer, Optional ByVal addNew As Boolean = False)

        _gridView.EditIndex = editIndex

        If _requeryHandler IsNot Nothing Then

            Dim t As DataTable = _requeryHandler()

            If addNew Then

                For Each col As DataColumn In t.Columns
                    col.AllowDBNull = True
                Next

                Dim newRow As DataRow = t.NewRow()
                t.Rows.Add(newRow)

            End If

            _gridView.DataSource = t

            If addNew Then
                _gridView.EditIndex = t.Rows.Count - 1
            End If

            _gridView.DataBind()

            For Each row As GridViewRow In _gridView.Rows

                Dim editMode As Boolean = (row.RowIndex = _gridView.EditIndex)

                SetVisibility(row, "uxDeleteButton", Not editMode)
                SetVisibility(row, "uxEditButton", Not editMode)
                SetVisibility(row, "uxSaveButton", editMode)
                SetVisibility(row, "uxCancelButton", editMode)

            Next

        End If

    End Sub

    '-- Event Handlers ----------------------------------------------------------------------------
    Private Sub _gridView_RowDataBound(ByVal sender As Object, ByVal e As _
    GridViewRowEventArgs) Handles _gridView.RowDataBound

        Try

            If e.Row IsNot Nothing AndAlso e.Row.RowType = DataControlRowType.DataRow AndAlso _
            e.Row.DataItem IsNot Nothing Then

                Dim dataRow As DataRow = CType(e.Row.DataItem, DataRowView).Row

                If dataRow IsNot Nothing Then

                    '-- Init Delete Button --------------------------------------------------------
                    If dataRow(_identifyingField) IsNot Nothing Then

                        Dim identifier As String = dataRow(_identifyingField).ToString()

                        Dim control As WebControl = _
                                CType(e.Row.FindControl("uxDeleteButton"), WebControl)

                        Dim button As ImageButton = Nothing

                        If control IsNot Nothing Then

                            button = CType(control, ImageButton)
                            button.OnClientClick = "confirm('Delete [" & _
                                                            identifier.Replace("'", "\'") & "]?');"

                        End If

                    End If

                End If

            End If

        Catch ex As Exception

            Throw ex

        End Try

    End Sub
    '----------------------------------------------------------------------------------------------
    Private Sub _gridView_RowEdit(ByVal sender As Object, ByVal e As GridViewEditEventArgs) _
    Handles _gridView.RowEditing

        BindToDataTable(e.NewEditIndex)

    End Sub
    '----------------------------------------------------------------------------------------------
    Private Sub _gridView_RowCancellingEdit(ByVal sender As Object, ByVal e As _
    GridViewCancelEditEventArgs) Handles _gridView.RowCancelingEdit

        BindToDataTable(-1)

    End Sub
    '----------------------------------------------------------------------------------------------
    Private Sub _gridView_RowDeleting(ByVal sender As Object, ByVal e As GridViewDeleteEventArgs) _
    Handles _gridView.RowDeleting

        If _deleteHandler IsNot Nothing And _requeryHandler IsNot Nothing Then

            Try

                _deleteHandler(_gridView.DataKeys(e.RowIndex))
                BindToDataTable(-1)

            Catch ex As Exception

                e.Cancel = True

            End Try

        End If

    End Sub
    '----------------------------------------------------------------------------------------------
    Private Sub _gridView_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs) _
    Handles _gridView.RowUpdating

        If _updateHandler IsNot Nothing And _requeryHandler IsNot Nothing Then

            Try

                _updateHandler(_gridView.DataKeys(e.RowIndex), _gridView.Rows(e.RowIndex))
                BindToDataTable(-1)

            Catch ex As Exception

                e.Cancel = True

            End Try

        End If

    End Sub
    '----------------------------------------------------------------------------------------------
    Public Function TryGetDataRow(ByVal row As GridViewRow, ByRef dataRow As DataRow) As Boolean

        Dim result As Boolean = False

        Dim drv As DataRowView = CType(row.DataItem, DataRowView)

        If drv IsNot Nothing Then

            dataRow = drv.Row
            result = (dataRow IsNot Nothing)

        End If

        Return result

    End Function

    '-- Helper Functions --------------------------------------------------------------------------
    Private Shared Sub SetVisibility(ByVal row As GridViewRow, ByVal controlName As String, ByVal _
    visible As Boolean)

        Dim control As WebControl = CType(row.FindControl(controlName), WebControl)

        If control IsNot Nothing Then
            control.Visible = visible
        End If

    End Sub
        

End Class

ScrewTurn Wiki version 3.0.1.400. Some of the icons created by FamFamFam. Except where noted, all contents Copyright © 1999-2018, Patrick Jasinski.