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

Page History: GridView Class - ASP.NET

Compare Page Revisions



« Older Revision - Back to Page History - Newer Revision »


Page Revision: Tue, Oct 27, 2009, 12:53 PM


This page is part of the Class Library Pages collection.
Click the icon to see the index.
This class supercedes the GridViewExtender class.

Table of Contents [Hide/Show]


   Features
   Sample Implementation
      ASPX Markup Code
      Code-Behind
         C#
         Visual Basic
      Adjust the Code
         Retrieve Data
         Save Data
         Delete Data
   Source Code
         C#
         Visual Basic

{outline||<1> - |

.<1> - }

Features

The GridView 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.

Sample Implementation

To use this control, you need to follow the instructions in the Consuming Custom Controls in ASP.NET article.

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 GridView 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.

<%-- TODO: Change the DataKeysNames property appropriate to your application --%>
<abc:GridView runat="server" ID="uxGridView" 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" 
                    />
                
            </ItemTemplate>
            
            <EditItemTemplate>
            
                <%-- TODO: Specify the validation group 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"
                    />
            
            </EditItemTemplate>
                            
        </asp:TemplateField>


    </Columns>


</abc:GridView>

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

Code-Behind

Copy the following code into your code-behind file.

C#

protected void Page_Load(object sender, EventArgs e)
{
    // TODO: Change the first parameter appropriate to your implementation
    uxGridView.Initialize("Description", 
                       new EmptyDelegate(QueryData), 
                       new DataKeyDelegate(DeleteData), 
                       new GridViewRowDelegate(UpdateData));

    if (!Page.IsPostBack)

        uxGridView.Requery();

}
private DataTable QueryData()
{
    return null;
    //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)
{
    uxGridView.AddNew();
}

Visual Basic

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

    ' TODO: Change the first parameter appropriate to your implementation
    uxGridView.Initialize("Description", _
                       New EmptyDelegate(AddressOf QueryData), _
                       New DataKeyDelegate(AddressOf DeleteData), _
                       New GridViewRowDelegate(AddressOf UpdateData))

    If Not Page.IsPostBack Then

        uxGridView.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

    uxGridView.AddNew()

End Sub

Adjust the Code

Retrieve Data

  1. Get SP — Write a stored procedure to retrieve the data
  2. Typed DataSet — In a typed dataset create a data table based on the stored procedure.
  3. Default Values — Set default values for new rows in the typed DataSet.
  4. QueryData — Adjust the code for the QueryData method to retrieve the appropriate data and return the typed DataTable.
  5. DataKeyNames — In the ASPX code, change the DataKeyNames property of the GridView.
  6. Columns — Add columns to the GridView to display/edit fields.
  7. IdentifyingField — On the uxGridView.Initialize() method call, adjust the first parameter.
  8. Test Display — Test that the grid displays rows correctly.

Save Data

  1. Save SP — Write a stored procedure that saves the data.
  2. UpdateData — Adjust the code for the UpdateData method to save changes to a row.
  3. Test UpdateData — Test the saving of a row.
  4. Test AddNew — Test the adding of a new row.

Delete Data

  1. Delete SP — Write a stored procedure to delete a row.
  2. DeleteData — Adjust the code for the DeleteData method to delete a row.
  3. Test DeleteData — Test the deleting of a row.

Source Code

C#

{copytext|SourceCs}
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);

namespace JasinskiSoftware
{
    public class GridView : System.Web.UI.WebControls.GridView
    {
        private string _identifyingField;
        private EmptyDelegate _requeryHandler;
        private DataKeyDelegate _deleteHandler;
        private GridViewRowDelegate _updateHandler;
        private HiddenField _rowCountField;

        //- Constructor -------------------------------------------------------------------------------
        public GridView()
        {
            this.AutoGenerateColumns = false;
            this.CellPadding = 3;
            this.CellSpacing = 0;
        }

        public void Initialize(string identifyingField, EmptyDelegate requeryHandler, 
            DataKeyDelegate deleteHandler, GridViewRowDelegate updateHandler)
        {
            Initialize(identifyingField, requeryHandler, deleteHandler, updateHandler, null);
        }

        public void Initialize(string identifyingField, EmptyDelegate requeryHandler, 
            DataKeyDelegate deleteHandler, GridViewRowDelegate updateHandler, HiddenField 
            rowCountField)
        {
            _identifyingField = identifyingField;
            _requeryHandler = requeryHandler;
            _deleteHandler = deleteHandler;
            _updateHandler = updateHandler;
            _rowCountField = rowCountField;

            base.RowDataBound 
                += new GridViewRowEventHandler(_gridView_RowDataBound);

            base.RowEditing
                += new GridViewEditEventHandler(_gridView_RowEditing);

            base.RowCancelingEdit 
                += new GridViewCancelEditEventHandler(_gridView_RowCancelingEdit);

            base.RowDeleting 
                += new GridViewDeleteEventHandler(_gridView_RowDeleting);

            base.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)
        {
            this.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);
                }

                this.DataSource = t;

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

                this.DataBind();
            }
        }
        //---------------------------------------------------------------------------------------------
        private int EditIndex
        {
            get { return this.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 = "return 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(base.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(base.DataKeys[e.RowIndex], base.Rows[e.RowIndex]);
                    BindToDataTable(-1);
                }
                catch
                {
                    e.Cancel = true;
                }
            }
        }

    }

}

Visual Basic

{copytext|SourceVb}
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports System.Diagnostics

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)

Namespace AcmeBroomCompany

    Public Class GridView

        Inherits System.Web.UI.WebControls.GridView
        Private _identifyingField As String
        Private _requeryHandler As EmptyDelegate
        Private _deleteHandler As DataKeyDelegate
        Private _updateHandler As GridViewRowDelegate
        Private _rowCountField As HiddenField

        '- Constructor and Initializer ----------------------------------------------------------- 
        Public Sub New()
            ' set default settings 
            Me.AutoGenerateColumns = False
            Me.CellPadding = 3
            Me.CellSpacing = 0
        End Sub
        Public Sub Initialize(ByVal identifyingField As String, ByVal requeryHandler As _
        EmptyDelegate, ByVal deleteHandler As DataKeyDelegate, ByVal updateHandler As _
        GridViewRowDelegate, Optional ByVal rowCountField As HiddenField = Nothing)

            _identifyingField = identifyingField
            _requeryHandler = requeryHandler
            _deleteHandler = deleteHandler
            _updateHandler = updateHandler
            _rowCountField = rowCountField

            AddHandler MyBase.RowDataBound, AddressOf _gridView_RowDataBound

            AddHandler MyBase.RowEditing, AddressOf _gridView_RowEditing

            AddHandler MyBase.RowCancelingEdit, AddressOf _gridView_RowCancelingEdit

            AddHandler MyBase.RowDeleting, AddressOf _gridView_RowDeleting

            AddHandler MyBase.RowUpdating, AddressOf _gridView_RowUpdating
        End Sub

        '- Public Methods ---------------------------------------------------------------------------- 
        Public Sub AddNew()

            If Me.Controls.Count <= 0 Or _rowCountField Is Nothing Then

                BindToDataTable(-1, True)

            Else

                Dim table As Table = CType(Me.Controls(0), Table)
                Dim rowIndex As Integer = table.Rows.Count
                RowCount += 1

                ' subtract one for the header
                While table.Rows.Count - 1 <= RowCount

                    Dim newGvRow As GridViewRow = Me.CreateRow(rowIndex, rowIndex, _
                                            DataControlRowType.DataRow, DataControlRowState.Insert)

                    Dim fields As DataControlField() = New DataControlField(Me.Columns.Count - 1) {}
                    MyBase.Columns.CopyTo(fields, 0)
                    MyBase.InitializeRow(newGvRow, fields)
                    table.Controls.AddAt(rowIndex, newGvRow)

                End While

            End If

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

        '- Private Methods --------------------------------------------------------------------------- 
        Private Sub BindToDataTable(ByVal editIndex As Integer)
            BindToDataTable(editIndex, False)
        End Sub
        Private Sub BindToDataTable(ByVal editIndex As Integer, ByVal addNew As Boolean)
            Try
                MyBase.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

                    MyBase.DataSource = t

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

                    MyBase.DataBind()

                End If
            Catch ex As Exception
                Throw ex
            End Try
        End Sub
        Private Property EditIndex() As Integer
            Get
                Return MyBase.EditIndex
            End Get
            Set(ByVal value As Integer)
                BindToDataTable(value)
            End Set
        End Property
        Private Property RowCount() As Integer
            Get
                Dim result As Integer
                If _rowCountField Is Nothing OrElse Not Integer.TryParse(_rowCountField.Value, _
                result) Then
                    result = -1
                End If
                Return result
            End Get
            Set(ByVal value As Integer)
                _rowCountField.Value = value.ToString()
            End Set
        End Property

        '- Event Handlers ---------------------------------------------------------------------------- 
        Private Sub _gridView_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)

            Try

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

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

                    If dataRow IsNot Nothing AndAlso dataRow(_identifyingField) IsNot Nothing Then

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

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

                        Dim button As ImageButton = Nothing

                        If control IsNot Nothing Then
                            button = TryCast(control, ImageButton)
                            button.OnClientClick = "return confirm('Delete [" & _
                                                            identifier.Replace("'", "\'") & "]?');"

                        End If
                    End If
                End If
            Catch ex As Exception
                Throw ex
            End Try
        End Sub
        Private Sub _gridView_RowEditing(ByVal sender As Object, ByVal e As GridViewEditEventArgs)
            BindToDataTable(e.NewEditIndex)
        End Sub
        Private Sub _gridView_RowCancelingEdit(ByVal sender As Object, ByVal e As _
        GridViewCancelEditEventArgs)
            BindToDataTable(-1)
        End Sub
        Private Sub _gridView_RowDeleting(ByVal sender As Object, ByVal e As _
        GridViewDeleteEventArgs)
            If _deleteHandler IsNot Nothing And _requeryHandler IsNot Nothing Then
                Try
                    _deleteHandler(MyBase.DataKeys(e.RowIndex))
                    BindToDataTable(-1)
                Catch
                    '(Exception ex) 
                    e.Cancel = True
                End Try
            End If
        End Sub

        ' This event handler should fire when the user click a row button with the "Update" command 
        Private Sub _gridView_RowUpdating(ByVal sender As Object, ByVal e As GridViewUpdateEventArgs)
            If _updateHandler IsNot Nothing And _requeryHandler IsNot Nothing Then
                Try
                    _updateHandler(MyBase.DataKeys(e.RowIndex), MyBase.Rows(e.RowIndex))
                    BindToDataTable(-1)
                Catch ex As Exception
                    Debug.Print(ex.Message)
                    e.Cancel = True
                End Try
            End If
        End Sub

    End Class
End Namespace

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