![]() |
Web Development »
ASP.NET »
Samples
Beginner
License: The Code Project Open License (CPOL)
Dating Website MailBox with Full FeaturesBy TV MogulGridView with AJAX Delete Confirmation, Select / Delete ALL with Memory Paging |
C#.NET 2.0, ASP.NET, Ajax, SQL 2008, Dev
|
||||||||||
|
Advanced Search |
|
|
|
||||||||||||||||
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:
GridView behave like a FormView CheckBoxes CheckBoxes with Paging ModalPopupExtender CheckBoxes using ModalPopupExtender 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.
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, 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
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();
}
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();
}
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();
}
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;"
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.
| You must Sign In to use this message board. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 3 Jan 2009 Editor: Deeksha Shenoy |
Copyright 2009 by TV Mogul Everything else Copyright © CodeProject, 1999-2009 Web12 | Advertise on the Code Project |