Thursday, August 27, 2009

Sorting and Paging a GridView

2 comments
Sorting can be tricky. But maintaining the sort order on paging is trickier
Here is a sample code for that

DataBase used is Northwind.
Table used is Products.

The ASPX



<asp:GridView ID="GridView1" runat="server"
AllowPaging="true"
AllowSorting="true"
AutoGenerateColumns="false"
DataKeyNames="ProductID"
PageSize="10"
OnPageIndexChanging="GridView1_PageIndexChanging"
OnSorting="GridView1_Sorting">
<Columns>
<asp:TemplateField HeaderText="ID" SortExpression="ProductID">
<ItemTemplate>
<asp:Label ID="lblProductID" runat="server"
Text='<%#Eval("ProductID") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Name" SortExpression="ProductName">
<ItemTemplate>
<asp:Label ID="lblProductName" runat="server"
Text='<%#Eval("ProductName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Stock" SortExpression="UnitsInStock">
<ItemTemplate>
<asp:Label ID="lblUnitsInStock" runat="server"
Text='<%#Eval("UnitsInStock") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>



The ASPX.CS



private const string ASCENDING = " ASC";
private const string DESCENDING = " DESC";
static private DataView dvProducts;

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dvProducts = new DataView(GetProductsFromDataTable());
BindGridView();
}
}

protected void GridView1_Sorting(object sender, GridViewSortEventArgs e)
{
string sortExpression = e.SortExpression;

if (GridViewSortDirection == SortDirection.Ascending)
{
GridViewSortDirection = SortDirection.Descending;
dvProducts.Sort = sortExpression + DESCENDING;
BindGridView();
}
else
{
GridViewSortDirection = SortDirection.Ascending;
dvProducts.Sort = sortExpression + ASCENDING;
BindGridView();
}
}

protected void GridView1_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
GridView1.PageIndex = e.NewPageIndex;
BindGridView();
}

private void BindGridView()
{
GridView1.DataSource = dvProducts;
GridView1.DataBind();
}

public SortDirection GridViewSortDirection
{
get
{
if (ViewState["sortDirection"] == null)
ViewState["sortDirection"] = SortDirection.Ascending;

return (SortDirection)ViewState["sortDirection"];
}
set { ViewState["sortDirection"] = value; }
}

private DataTable GetProductsFromDataTable()
{
DataTable dtProductsTemp = new DataTable();
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
{
using (SqlDataAdapter adapProducts = new SqlDataAdapter("Select * from Products", conn))
{
adapProducts.Fill(dtProductsTemp);
}
}
return dtProductsTemp;
}



Extra namespace used



using System.Data.SqlClient;


Read more...

Saturday, July 18, 2009

Paging in Repeater

0 comments
Heres a sample on how to implement Paging on a Repeater.

The Output



The ASPX

<asp:Repeater ID="rptrProducts" runat="server">
<HeaderTemplate>
<table border="1">
<tr style="background-color:Gray;">
<td>
Product Name
</td>
<td>
Quantity Per Unit
</td>
<td>
Units On Order
</td>
<td>
Discontinued
</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="lblProductName" runat="server" Text='<%#Eval("ProductName") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblQuantityPerUnit" runat="server" Text='<%#Eval("QuantityPerUnit") %>'></asp:Label>
</td>
<td>
<asp:Label ID="lblUnitsOnOrder" runat="server" Text='<%#Eval("UnitsOnOrder") %>'></asp:Label>
</td>
<td>
<asp:CheckBox ID="chkDiscontinued" runat="server" Checked='<%#Eval("Discontinued") %>'
Enabled="false" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
<tr align="right" style="background-color:Gray;">
<td colspan="4">
<asp:LinkButton ID="lnkFirst" runat="server"
ForeColor="Black"
Text="First" onclick="lnkFirst_Click">
</asp:LinkButton>&nbsp;
<asp:LinkButton ID="lnkPrevious" runat="server"
ForeColor="Black"
Text="Previous"
OnClick="lnkPrevious_Click">
</asp:LinkButton>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
Now Showing Page&nbsp;
<asp:DropDownList ID="ddlpageNumbers" runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="ddlpageNumbers_SelectedIndexChanged">
</asp:DropDownList>&nbsp;of&nbsp;
<asp:Label ID="lblTotalPages" runat="server">
</asp:Label>&nbsp;Pages.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<asp:LinkButton ID="lnkNext" runat="server"
ForeColor="Black"
Text="Next" onclick="lnkNext_Click">
</asp:LinkButton>&nbsp;
<asp:LinkButton ID="lnkLast" runat="server"
ForeColor="Black"
Text="Last" onclick="lnkLast_Click">
</asp:LinkButton>
</td>
</tr>
</table>


The ASPX.CS

public partial class Repeaters_Paging : System.Web.UI.Page
{
#region "Local Variables and Declarations"

private const bool blnAllowPaging = true;
private const int iPageSize = 10;

private static PagedDataSource pgdProducts = new PagedDataSource();

#endregion

#region "Page Load Event"

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindRepeater();
}
}

#endregion

#region "Footer LinkButtons"

protected void lnkFirst_Click(object sender, EventArgs e)
{
ThisPageNumber = 0;
BindRepeater();
}

protected void lnkPrevious_Click(object sender, EventArgs e)
{
--ThisPageNumber;
BindRepeater();
}

protected void lnkNext_Click(object sender, EventArgs e)
{

++ThisPageNumber;
BindRepeater();
}

protected void lnkLast_Click(object sender, EventArgs e)
{
ThisPageNumber = pgdProducts.PageCount - 1;
BindRepeater();
}

#endregion

#region "Footer DropDownList"

protected void ddlpageNumbers_SelectedIndexChanged(object sender, EventArgs e)
{
ThisPageNumber = ddlpageNumbers.SelectedIndex;
BindRepeater();
}

#endregion

#region "Custom Functions"

private void BindRepeater()
{
pgdProducts.AllowPaging = blnAllowPaging;
pgdProducts.PageSize = iPageSize;
pgdProducts.DataSource = GetProductsDataView();

pgdProducts.CurrentPageIndex = ThisPageNumber;
lblTotalPages.Text = pgdProducts.PageCount.ToString();
FillPagesDropDownList(pgdProducts.PageCount);

lnkFirst.Enabled = !pgdProducts.IsFirstPage;
lnkPrevious.Enabled = !pgdProducts.IsFirstPage;
lnkNext.Enabled = !pgdProducts.IsLastPage;
lnkLast.Enabled = !pgdProducts.IsLastPage;
ddlpageNumbers.SelectedIndex = pgdProducts.CurrentPageIndex;

rptrProducts.DataSource = pgdProducts;
rptrProducts.DataBind();
}

private DataView GetProductsDataView()
{
DataTable dtProductsTemp = new DataTable();
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
{
using (SqlDataAdapter adapProducts = new SqlDataAdapter("Select * from Products", conn))
{
adapProducts.Fill(dtProductsTemp);
}
}
return dtProductsTemp.DefaultView;

}

private void FillPagesDropDownList(int iTotalPages)
{
ddlpageNumbers.Items.Clear();
for (int i = 1; i <= iTotalPages; i++)
{
ddlpageNumbers.Items.Add(new ListItem(i.ToString(), i.ToString()));
}
}

#endregion

#region "Properties"

private int ThisPageNumber
{
get
{
object obj = ViewState["ThisPageNumber"];
return (obj == null) ? 0 : (int)obj;
}
set
{
this.ViewState["ThisPageNumber"] = value;
}
}

#endregion

}

Extra Namespace used

using System.Data.SqlClient;

P.S: DataBase used is Northwind
Read more...

Friday, May 15, 2009

SubTotals in GridView

1 comments
To display Sub Totals in a GridView is a situation that arise frequently.

Here's a sample on how to do it using GridView.

First we need a table TBL_Patients. Here's the structure



Now lets populate some sample values to it.



The ASPX


<asp:GridView ID="gvwPatientBill" runat="server"
AutoGenerateColumns="false"
DataKeyNames="BillID"
GridLines="Both"
OnRowDataBound="gvwPatientBill_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Bill ID">
<ItemTemplate>
<asp:Label ID="lblBillID" runat="server"
Text='<%# Eval("BillID") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Patient ID">
<ItemTemplate>
<asp:Label ID="lblPatientID" runat="server"
Text='<%# Eval("PatientID") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Patient Name">
<ItemTemplate>
<asp:Label ID="lblPatientName" runat="server"
Text='<%# Eval("PatientName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Patient Ward">
<ItemTemplate>
<asp:Label ID="lblPatientWard" runat="server"
Text='<%# Eval("PatientWard") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Bill Amount">
<ItemTemplate>
<asp:Label ID="lblBillAmount" runat="server"
Text='<%# Eval("BillAmount") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
<HeaderStyle BackColor="Black" ForeColor="White" />
</asp:GridView>

The ASPX.CS

int iPatientIDCount = 0;
int iRowsCount = 0;
int iAddBills = 0;
string sPatientID = "";

protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindGridView();
}
}

private void BindGridView()
{
DataTable dtPatientBills = new DataTable();
string strSelectCommand = "SELECT * FROM TBL_PatientBills ORDER BY PatientID";
using (SqlConnection sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString))
{
using (SqlDataAdapter adapPatientBills = new SqlDataAdapter(strSelectCommand, sqlConn))
{
adapPatientBills.Fill(dtPatientBills);
}
}
iRowsCount = dtPatientBills.Rows.Count - 1;
gvwPatientBill.DataSource = dtPatientBills;
gvwPatientBill.DataBind();
}

protected void gvwPatientBill_RowDataBound(object sender, GridViewRowEventArgs e)
{

if (e.Row.RowType == DataControlRowType.DataRow)
{
string sName = "";
if (e.Row.RowIndex == 0)
{
sPatientID = ((Label)e.Row.FindControl("lblPatientID")).Text;
iAddBills = Convert.ToInt32(((Label)e.Row.FindControl("lblBillAmount")).Text);
}
else
{
sName = ((Label)gvwPatientBill.Rows[e.Row.RowIndex - 1].FindControl("lblPatientName")).Text;
iPatientIDCount = iPatientIDCount + 1;
if (sPatientID == ((Label)e.Row.FindControl("lblPatientID")).Text)
{
iAddBills += Convert.ToInt32(((Label)e.Row.FindControl("lblBillAmount")).Text);
}
else
{
sPatientID = ((Label)e.Row.FindControl("lblPatientID")).Text;
Table tblTemp = (Table)this.gvwPatientBill.Controls[0];
int intIndex = tblTemp.Rows.GetRowIndex(e.Row);
GridViewRow gvrSubTotal = CreateGridViewRow(
intIndex,
"#8FD8D8",
gvwPatientBill.Columns.Count,
"Total for " + sName + " in " + iPatientIDCount + " Entries: " + iAddBills,
20);
tblTemp.Controls.AddAt(intIndex, gvrSubTotal);
iPatientIDCount = 0;
iAddBills = Convert.ToInt32(((Label)e.Row.FindControl("lblBillAmount")).Text);
}
if (iRowsCount == e.Row.RowIndex)
{
sName = ((Label)e.Row.FindControl("lblPatientName")).Text;
Table tblTemp = (Table)this.gvwPatientBill.Controls[0];
int intIndex = tblTemp.Rows.GetRowIndex(e.Row) + 1;

GridViewRow gvrLast = CreateGridViewRow(
intIndex,
"#8FD8D8",
gvwPatientBill.Columns.Count,
"Total for " + sName + " in " + iPatientIDCount + " Entries: " + iAddBills,
20);
tblTemp.Controls.AddAt(intIndex, gvrLast);
}
}
}
}

private GridViewRow CreateGridViewRow(int iCurrentIndex, string sTableBackColor,int iTableColumnSpan, string sTableText, int iTableHeight)
{
GridViewRow gvrTemp = new GridViewRow(iCurrentIndex, iCurrentIndex, DataControlRowType.Separator, DataControlRowState.Normal);
TableCell cellTemp = new TableCell();
cellTemp.BackColor = System.Drawing.ColorTranslator.FromHtml("#8FD8D8");
cellTemp.Font.Bold = true;
cellTemp.ColumnSpan = iTableColumnSpan;
cellTemp.HorizontalAlign = HorizontalAlign.Left;
cellTemp.Text = sTableText;
cellTemp.Height = Unit.Pixel(iTableHeight);
gvrTemp.Cells.Add(cellTemp);
return gvrTemp;
}


And the final result looks like this.


NB: Its a no-no if you wanna implement Paging and Sorting here. For that, we have to use the wonderful third party
GridView controls like Teleriks RadGrid and all
Read more...