January 18, 2010 by Christoff Truter C# ASP.NET
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 ('Jurgens', 'Truter', getdate() - 10)
INSERT INTO friends(firstname, lastname, created) VALUES ('Gerhardt', '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
<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;
}
}
}
}
}
protected void gvFriends_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
LinkButton linkButton = (from headerCells in e.Row.Cells.OfType<DataControlFieldHeaderCell>()
let lb = (headerCells.HasControls()) ? headerCells.Controls[0] as LinkButton : null
where lb != null
&& ((GridView)sender).SortExpression == lb.CommandArgument
select lb).SingleOrDefault();
if (linkButton != null)
{
Image image = new Image();
image.ImageUrl = (((GridView)sender).SortDirection == SortDirection.Ascending) ? "~/images/asc.gif" : "~/images/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 ;)