CSTrüter HomeArticlesDownloadsAbout meContact me
How to enable the filestream feature in SQL 2008 - Alternative way to store blobs(files) via SQL 2010-08-21 19:31:56
How to create a Singleton Pattern in C# 2010-08-10 22:52:52
How to prevent that threads access shared resources concurrently via Monitor. 2010-08-06 15:31:15
A quick review of the book PHP 6 and MySQL 5 for Dynamic Web Sites: Visual QuickPro Guide written by Larry Ullman 2010-08-04 21:48:58
How to prevent that threads access shared resources concurrently via Mutex. 2010-08-03 14:42:36
How to stop propagation of javascript events 2010-07-25 21:59:29
Post about how Pete the web developer fixed his sitemap 2010-07-17 15:12:02
How to setup an out of process session service 2010-07-08 17:51:46
How to display/add images from/to a SQL Database 2010-07-04 23:15:15
How to register a custom URL protocol handler 2010-06-28 20:34:01
Creating a WYSIWYG textbox for your website is actually quite simple. 2007-02-01 12:00:00
Move items between two listboxes in ASP.net(C#, VB.NET) and PHP 2008-06-12 17:07:43
Firefox word wrapping issues 2008-06-09 09:51:21
Populate a TreeView control in a windows application. 2009-08-27 16:01:03
2007-02-22 12:00:00
Source code for the following post can be downloaded here. The following post is a bit of a follow up post on the post I did a while ago about paging. Equally to paging, sorting is also one of those common tasks when working with data. Similarly to the paging post we create a table, except we're adding a datetime field in this example, which tells us when an user was added to our "system". CREATE TABLE [dbo].[friends]( [id] [int] IDENTITY(1,1) NOT NULL, [firstname] [varchar](50) NOT NULL, [lastname] [varchar](50) NOT NULL, [created] [datetime] NOT NULL, CONSTRAINT [PK_friends] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] The default value for the create date: ALTER TABLE [dbo].[friends] ADD CONSTRAINT [DF_friends_created] DEFAULT (getdate()) FOR [created] You'll also need to create some indexes for the fields you're planning to do sorting on, to avoid table scans: CREATE NONCLUSTERED INDEX [ix_friends] ON [dbo].[friends] ( [firstname] ASC, [lastname] ASC, [created] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] Add some data: INSERT INTO friends(firstname, lastname, created) VALUES ('Julie', 'Truter', getdate() - 10) INSERT INTO friends(firstname, lastname, created) VALUES ('Eugene', 'Stander', getdate() - 50) INSERT INTO friends(firstname, lastname, created) VALUES ('Pam', 'Nizar', getdate() - 120) INSERT INTO friends(firstname, lastname, created) VALUES ('Alexander', 'Mehlhorn', getdate() - 4) INSERT INTO friends(firstname, lastname, created) VALUES ('Roland', 'Cooper', getdate() - 10) INSERT INTO friends(firstname, lastname, created) VALUES ('Loren', 'Stevens', getdate() -2) INSERT INTO friends(firstname, lastname, created) VALUES ('Edward', 'Anderson', getdate() - 5) INSERT INTO friends(firstname, lastname, created) VALUES ('Wayne', 'Kleynhans', getdate() - 13) The stored procedure we're going to use to assist us in sorting, will look something like this: CREATE PROCEDURE [dbo].[sortFriends] @sort AS VARCHAR(20) AS BEGIN SELECT id, firstname, lastname, created FROM friends ORDER BY CASE @sort WHEN 'firstname' THEN firstname WHEN 'lastname' THEN lastname ELSE NULL END ASC, CASE @sort WHEN 'created' THEN created ELSE NULL END ASC, CASE @sort WHEN 'firstname DESC' THEN firstname WHEN 'lastname DESC' THEN lastname ELSE NULL END DESC, CASE @sort WHEN 'created DESC' THEN created ELSE NULL END DESC END Notice the case statements in the order by clause, I seperated the created field from the other (firstname, lastname) fields - if we process these fields in the same case statement, we'll need to convert the datetime field to a varchar - which I am avoiding for performance reasons. Also notice the "ELSE NULL", SQL will ignore these order conditions, if our case condition isn't met. Moving on to the ASP.net side of things.. In the following snippet we create a gridview control, notice the sortexpression attributes, those are the expressions we're going to send to our stored procedure. Note: the control will automatically concatenate our descending command if needed, eg firstname DESC. <asp:GridView ID="gvFriends" runat="server" DataSourceID="obsFriends" AllowSorting="true" AutoGenerateColumns="false" OnRowCreated="gvFriends_RowCreated"> <Columns> <asp:BoundField DataField="firstname" HeaderText="Firstname" SortExpression="firstname" /> <asp:BoundField DataField="lastname" HeaderText="Lastname" SortExpression="lastname" /> <asp:BoundField DataField="created" HeaderText="Created" SortExpression="created" DataFormatString="{0:d}" /> </Columns> </asp:GridView> <asp:ObjectDataSource ID="obsFriends" runat="server" SelectMethod="sortFriends" TypeName="friends" SortParameterName="sort"></asp:ObjectDataSource> This is what our select method is going to look like: [DataObject()] public class friends { [DataObjectMethod(DataObjectMethodType.Select)] public static DataTable sortFriends(String sort) { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString)) { using (SqlCommand command = new SqlCommand("sortFriends", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@sort", sort); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } } When an user clicks on a field in the header of the gridview, it will send the appropriate command to the stored procedure and sort our results. Unfortunately M$ didn't provide functionality which displays which field and which direction (descending/ascending) are currently being sorted. Luckily this is functionality we can add ourselves, we attach the following code to the rowcreated event of the gridview. if (e.Row.RowType == DataControlRowType.Header) { List<LinkButton> linkButtons = (from headerCells in e.Row.Cells.OfType<DataControlFieldHeaderCell>() let linkButton = (headerCells.HasControls()) ? headerCells.Controls[0] as LinkButton : null where linkButton != null && ((GridView)sender).SortExpression == linkButton.CommandArgument select linkButton).ToList<LinkButton>(); foreach (LinkButton linkButton in linkButtons) { Image image = new Image(); image.ImageUrl = String.Concat("~/images/", (((GridView)sender).SortDirection == SortDirection.Ascending ? "asc" : "desc"), ".gif"); linkButton.Controls.Add(new LiteralControl(String.Concat(linkButton.Text, " "))); linkButton.Controls.Add(image); } } You will notice I wrote a LINQ query to retrieve the linkbutton(s) currently "responsible" for sorting - alternatively one can simply retrieve them using a foreach statement, but I felt lucky ;) Once we find them, we add the proper picture to these controls, which gives us a visible representation of which columns are currently being sorted.
CREATE TABLE [dbo].[friends]( [id] [int] IDENTITY(1,1) NOT NULL, [firstname] [varchar](50) NOT NULL, [lastname] [varchar](50) NOT NULL, [created] [datetime] NOT NULL, CONSTRAINT [PK_friends] PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]
ALTER TABLE [dbo].[friends] ADD CONSTRAINT [DF_friends_created] DEFAULT (getdate()) FOR [created]
CREATE NONCLUSTERED INDEX [ix_friends] ON [dbo].[friends] ( [firstname] ASC, [lastname] ASC, [created] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
INSERT INTO friends(firstname, lastname, created) VALUES ('Julie', 'Truter', getdate() - 10) INSERT INTO friends(firstname, lastname, created) VALUES ('Eugene', 'Stander', getdate() - 50) INSERT INTO friends(firstname, lastname, created) VALUES ('Pam', 'Nizar', getdate() - 120) INSERT INTO friends(firstname, lastname, created) VALUES ('Alexander', 'Mehlhorn', getdate() - 4) INSERT INTO friends(firstname, lastname, created) VALUES ('Roland', 'Cooper', getdate() - 10) INSERT INTO friends(firstname, lastname, created) VALUES ('Loren', 'Stevens', getdate() -2) INSERT INTO friends(firstname, lastname, created) VALUES ('Edward', 'Anderson', getdate() - 5) INSERT INTO friends(firstname, lastname, created) VALUES ('Wayne', 'Kleynhans', getdate() - 13)
CREATE PROCEDURE [dbo].[sortFriends] @sort AS VARCHAR(20) AS BEGIN SELECT id, firstname, lastname, created FROM friends ORDER BY CASE @sort WHEN 'firstname' THEN firstname WHEN 'lastname' THEN lastname ELSE NULL END ASC, CASE @sort WHEN 'created' THEN created ELSE NULL END ASC, CASE @sort WHEN 'firstname DESC' THEN firstname WHEN 'lastname DESC' THEN lastname ELSE NULL END DESC, CASE @sort WHEN 'created DESC' THEN created ELSE NULL END DESC END
<asp:GridView ID="gvFriends" runat="server" DataSourceID="obsFriends" AllowSorting="true" AutoGenerateColumns="false" OnRowCreated="gvFriends_RowCreated"> <Columns> <asp:BoundField DataField="firstname" HeaderText="Firstname" SortExpression="firstname" /> <asp:BoundField DataField="lastname" HeaderText="Lastname" SortExpression="lastname" /> <asp:BoundField DataField="created" HeaderText="Created" SortExpression="created" DataFormatString="{0:d}" /> </Columns> </asp:GridView> <asp:ObjectDataSource ID="obsFriends" runat="server" SelectMethod="sortFriends" TypeName="friends" SortParameterName="sort"></asp:ObjectDataSource>
[DataObject()] public class friends { [DataObjectMethod(DataObjectMethodType.Select)] public static DataTable sortFriends(String sort) { using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString)) { using (SqlCommand command = new SqlCommand("sortFriends", connection)) { command.CommandType = CommandType.StoredProcedure; command.Parameters.AddWithValue("@sort", sort); using (SqlDataAdapter adapter = new SqlDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } }
if (e.Row.RowType == DataControlRowType.Header) { List<LinkButton> linkButtons = (from headerCells in e.Row.Cells.OfType<DataControlFieldHeaderCell>() let linkButton = (headerCells.HasControls()) ? headerCells.Controls[0] as LinkButton : null where linkButton != null && ((GridView)sender).SortExpression == linkButton.CommandArgument select linkButton).ToList<LinkButton>(); foreach (LinkButton linkButton in linkButtons) { Image image = new Image(); image.ImageUrl = String.Concat("~/images/", (((GridView)sender).SortDirection == SortDirection.Ascending ? "asc" : "desc"), ".gif"); linkButton.Controls.Add(new LiteralControl(String.Concat(linkButton.Text, " "))); linkButton.Controls.Add(image); } }
The company I am currently working for as software developer.
Collection of C# snippets 2010-05-22 01:06:19
Collection of MS SQL snippets 2010-05-22 00:55:15
Collection of JavaScript snippets 2010-05-22 00:37:57
Collection of ASP.net snippets 2010-05-22 00:29:56
Collection of PHP snippets 2010-05-22 00:06:45
a Parallel reference of programming languages 2009-09-10 12:48:23
a tutorial explaining how to develop a simple login using PHP and MySQL 2009-09-05 18:26:47
An article looking at adding some kind of event driven model to PHP 5 2008-07-28 12:48:09
It is very simple creating your own rss reader, the following article looks at a few methods of doing this. 2008-06-23 13:18:25
A quick reference about working with dropdown boxes (select element) in javascript. 2007-02-17 16:36:41
Collection of funny programming articles 2006-10-08 14:23:43