Click here to Skip to main content
Click here to Skip to main content

Dating Website MailBox with Full Features

, 3 Jan 2009
Rate this:
Please Sign up or sign in to vote.
GridView with AJAX Delete Confirmation, Select / Delete ALL with Memory Paging

Introduction

As I said in another article I posted, I had some free time and I decided to write a dating website and quickly learned that a dating website has more challenges than any other type of website I have ever built. In creating a GridView to display the messages from other members, I needed to implement the ability to delete messages. One issue I ran into was that of providing Delete Confirmation on member's messages and I noticed that there are articles that show how to implement confirm/delete in AJAX in various ways. And there are articles that show how to implement retaining checked checkboxes with paging and select all checkboxes. And there are articles on deleting all selected items in a GridView, etc. The problem is that each of these methods wasn't completely reliable under certain conditions and I couldn't find any examples of combining all of these operations in one GridView. So I decided to write this article about the approach I took to combine all of these requirements into one GridView sample that does the following:

  • Make a GridView behave like a FormView
  • Implement Select / Un-Select All CheckBoxes
  • Retain Checked CheckBoxes with Paging
  • Implement Confirm / Delete for A Single Selected Row using ModalPopupExtender
  • Implement Confirm / Delete for All Checked CheckBoxes using ModalPopupExtender

Giving the GridView FormView Properties

Most experienced web developers will probably say that this is obvious but many beginners or inexperienced web developers may not realize that you can put multiple fields into a single column of a GridView. In this sample I added the Username, Subject and MsgDate fields to the second column of the GridView to achieve a nicer look. In the first column I have the picture of the member who sent the message and this is added dynamically using an IHttpHandler, namely:

src='<%#"ShowImage.ashx?InboxImage="+Eval("FromProfileId") %>'

I also added in the sample project an asynchronous version of this Handler as well, namely, ImagesAsync.ashx. Note that the last 2 columns could have been put together in one column with both the fields for checking and deleting. I didn't add an Images table to the sample, you can easily do that to fit your own particular needs, so the sample defaults to the "no pic" image.

The Singleton Class

I decided to use a Singleton class with an ArrayList to store and retrieve the states of the checked CheckBoxes in the GridView, as follows:

//In the Singleton class, we have an ArrayList to hold checked values:
ArrayList MessagesIDList = new ArrayList(); 
public ArrayList messagesIDList 
{
   get { return MessagesIDList; } 
   set { MessagesIDList = value; } 
}

// Private constructor to create a singleton object 
// which cannot be created from outside this class
private singleton()
{
}

// Create static method using class name so no object instance is
// required to call it. This will always return a single instance 
// of this class, either newly created or from the session
public static singleton GetCurrentSingleton()
{
   singleton oSingleton;
   if (null == System.Web.HttpContext.Current.Session[SESSION_SINGLETON])
   {
      // No current session object exists, use private constructor to 
      // create an instance, place it into the session
      oSingleton = new singleton();
      System.Web.HttpContext.Current.Session[SESSION_SINGLETON] = oSingleton;
   }
   else
   {
      // Retrieve the instance that was already created
      oSingleton = 
         (singleton)System.Web.HttpContext.Current.Session[SESSION_SINGLETON];
   }
   // Return single instance of class stored in the session
   return oSingleton;
}

//In our webpage code
private void SaveCheckedValues() 
{ 
   singleton oSingleton = singleton.GetCurrentSingleton(); 
   int index = -1; 
   foreach (GridViewRow row in gvInbox.Rows) 
   {
      index = (int)gvInbox.DataKeys[row.RowIndex].Value; 
      bool result = ((CheckBox)row.FindControl("cb1")).Checked; 
      if (result) 
      { 
         if (!oSingleton.messagesIDList.Contains(index)) 
            oSingleton.messagesIDList.Add(index); 
      } 
      else 
         oSingleton.messagesIDList.Remove(index); 
   } 
}

//in our webpage code
private void LoadSavedCheckValues() 
{ 
   singleton oSingleton = singleton.GetCurrentSingleton();
   if (oSingleton.messagesIDList != null && oSingleton.messagesIDList.Count > 0) 
   { 
      foreach (GridViewRow row in gvInbox.Rows) 
      { 
         int index = (int)gvInbox.DataKeys[row.RowIndex].Value; 
         if (oSingleton.messagesIDList.Contains(index)) 
         { 
            CheckBox myCheckBox = (CheckBox)row.FindControl("cb1"); 
            myCheckBox.Checked = true; 
         } 
      } 
   } 
}

The ArrayList holds the checked CheckBoxes regardless of what page we are on and we can easily loop through this array to find the MessageIds of checked messages that we want to delete.

The Stored Procedure

The Stored Procedure, usp_GetMessages, serves two functions, namely, retrieving messages and deleting messages. We pass in a parameter that is a comma delimited string of the MessageIds we want to delete and the SQL function, ufn_CsvToInt, takes this string and converts it to a table of integers that we can use with the SQL "IN" function.

CREATE PROCEDURE [dbo].[usp_GetMessages] 
   @ProfileId INT, 
   @Username NVARCHAR(20), 
   @ListMessageIds VARCHAR(MAX) 
AS 
SET NOCOUNT ON 
declare @now datetime 
set @now = GETUTCDATE() 
IF(LEN(@ListMessageIds) > 0) 
   BEGIN 
      UPDATE [Mailbox] 
      SET [MsgDeleted] = 1 ,
      [Box] = '' ,
      [FromProfileId] = '' ,
      [FromUsername] = '' ,
      [Subject] = '' ,
      [Body] = '' ,
      [Tag] = '' 
      WHERE ( ([ProfileId] = @ProfileId) AND ([MessageId] _
		IN(SELECT * FROM dbo.ufn_CsvToInt(@ListMessageIds))) ) 
   END 
   BEGIN 
      SELECT [MessageId]
            ,[ProfileId]
            ,[Box]
            ,[FromProfileId]
            ,[FromUsername] 
            ,[Subject] 
            ,[Body] 
            ,[Tag] 
            ,convert(varchar, [MsgDate], 107) AS zdate 
            ,[MsgDate] 
            ,[MsgRead] 
            ,[MsgReplied] 
            ,[MsgDeleted] 
      FROM [Mailbox] WHERE (([ProfileId] = @ProfileId) AND ([MsgDeleted] <> 1)) 
   END 

Implementing Single Row Delete

The first thing I did was to implement the ability for the user to delete a single row by clicking on the red "X" ImageButton in the column of each message. When the user clicks on this ImageButton, we get row from the button's NamingContainer and the MessageId from the DataKey from that row and pass that as a parameter to usp_GetMessages as follows:

protected void BtnDelete_Click(object sender, ImageClickEventArgs e) 
{ 
   int index = -1; 
   ImageButton btnDelete = sender as ImageButton; 
   GridViewRow row = (GridViewRow)btnDelete.NamingContainer; 
   index = (int)gvInbox.DataKeys[row.RowIndex].Value; 
   SaveCheckedValues(); 
   PopulateMailbox("", index.ToString()); 
   LoadSavedCheckValues(); 
}

Implementing Multiple Deletes of Checked Rows

The button "deleted selected" allows the user to delete all the messages that have been checked. We call SaveCheckedValues() and then we loop through the ArrayList to create a comma delimited string of the MessageIds that have been checked as follows:

protected void btnDeleteSelected_Click(object sender, EventArgs e) 
{ 
   SaveCheckedValues(); 
   singleton oSingleton = singleton.GetCurrentSingleton(); 
   string sDelete = string.Empty; 
   if (oSingleton.messagesIDList != null && oSingleton.messagesIDList.Count > 0) 
   { 
      for (int i = 0; i < oSingleton.messagesIDList.Count; i++ ) 
      { 
         if (sDelete.Length < 1) 
            sDelete = oSingleton.messagesIDList[i].ToString(); 
         else 
            sDelete = sDelete + "," + oSingleton.messagesIDList[i].ToString(); 
      } 
   } 

   if (sDelete.Length < 1) return; 
   SaveCheckedValues(); 
   PopulateMailbox("", sDelete); 
   LoadSavedCheckValues(); 
}

The Select All CheckBox

There must be twenty articles and postings that illustrate how to add a checkbox to select all the checkboxes in a GridView but none of them that I found included checking across all the pages that the user could select. One way that many people use is to add an attribute for the onclick event on the CheckBox in the header as follows:

protected void gvInbox_RowDataBound(object sender, GridViewRowEventArgs e) 
{ 
   if (e.Row.RowType == DataControlRowType.Header) 
   {  
      ((CheckBox)e.Row.FindControl("cbSelectAll")).Attributes.Add("onclick", 
       "javascript:SelectAll('" + 
        ((CheckBox)e.Row.FindControl("cbSelectAll")).ClientID + "')"); 
   } 
}

// I added this event which is also necessary to actually make the code above work
// where paging in the GridView is implemented is the following:
protected void cbSelectAll_CheckedChanged(object sender, EventArgs e) 
{ 
   SaveCheckedValues(); 
}

The ModalPopupExtender

When the ImageButton with the "X" is clicked or the "delete selected" button is clicked, we call the same handler for both, namely:

OnClientClick="showConfirm(this); return false;"

Summary

I tried to implement ALL the features in one GridView with the least amount of code in one sample that I posted which is what you would do in a real dating application. There have been many articles showing how to do all of these things separately BUT when you try to put all of these techniques together in one GridView, things stop working and need a bit of tweaking to work like they did when isolated. I am sure there are other ways to accomplish this, but I have found that the approach here has worked for me reliably. If you have any questions, please feel free to contact me at tvmogul1@yahoo.com.

History

  • 3rd January, 2009: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

William SerGio
Software Developer (Senior) http://www.SerGioApps.com
United States United States
I love coding and develop desktop apps (C++, C#, Java), websites, and mobile apps (iPhone, Android, Blackberry, iPad, PhoneGap/Cordova).
 
I have written software for Microsoft, MySpace.com, Quicken (Intuit), Mellon Bank, U.S. Army, U.S. Navy, Franklin Templeton, Pepsi, Universal Studios, Ryder Systems, AVID, Media 100, etc.
 
Listed in the Marquis Who's Who in America and Who's Who in Advertising.
 
Bill SerGio
http://www.SerGioApps.com
http://www.SwipeClouds.com

Comments and Discussions

 
GeneralMy vote of 5 PinmemberBill SerGio, The Infomercial King22-Sep-11 22:39 
GeneralMy vote of 5 PinmemberShai Raiten5-Jul-11 6:24 
GeneralMy vote of 5 Pinmemberthatraja19-Nov-10 4:07 
GeneralShowmessage.aspx Pinmembermacupryk2-Aug-10 14:01 
GeneralShowMessage.aspx missing Pinmembereyale1-Oct-09 3:37 
GeneralRe: ShowMessage.aspx missing PinmemberTV Mogul1-Oct-09 3:43 
Hi,
 
thank you...
 
ShowMessage.aspx is just any web page you want to display the message--there isn't anything unique about it--just add any page and put something on it that you want to display.
 
Bill
 
http://www.MatchElf.com

GeneralMy vote of 2 PinmemberAndrey Mazoulnitsyn5-Jul-09 9:11 
GeneralDating Website Pinmembernbohr99a26-Feb-09 2:33 
GeneralNice Article Pinmemberbennyj434-Jan-09 3:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140827.1 | Last Updated 3 Jan 2009
Article Copyright 2009 by William SerGio
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid