Tuesday, December 22, 2009

Gray Scale images in all Browsers

7 comments
Its been a while since I blogged on anything.
Today I came across a post at forums.asp.net: change color image to gray scale

GrayScale - Converts the colors of the object to 256 shades of gray.
An example will be



Since GrayScale filter is a filter present in the Internet Explorer,
we can achieve this result in IE simply by using the css property
.greyscale_filter{ 
 filter: gray;
}
or
.greyscale_filter{
 -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)";
 filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}
Here the second method is more advanced and must have Internet Explorer 5.5 or later to work properly.

There are number of filters in IE apart from GrayScale. Here are some lists

1. Static filters by MSDN
2. CSS Visual Filters
3. IE Multimedia filters reference


This is the case with Internet Explorer.
Now the big question.

Why does not the GrayScale filter work with browsers like Chrome, Firefox and Safari?
Simple. The filter is specific to IE only.

While I was searching through the internet for a good solution, I found this at SO
There I discovered a wonderful javascript coder named James Padolsey who is just 19!

Copied his GrayScale.js which according to James Padolsey is

Grayscale.js is an experimental attempt to emulate Microsoft's
proprietary 'grayscale' filter (available in most IE versions).

And it worked like a charm.

So here are the steps involved in achieving the hover effect

1. Grab the GrayScale.js from James Padolsey's site. (The link is here)

2. Add refernce to jQuery. Please note that jQuery is not required for grayscale.js - it's only used for this demo
Its better to refer jQuery like this (Read Dave Ward ka Encosia on this topic)
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
  
than
<script type="text/javascript" src="/js/jQuery.min.js"></script>
  
3. Add a small javascript snippet like this
$(document).ready(function(){
     $('img.greyonhover').hover(function(){
    grayscale(this);
   }, function(){
    grayscale.reset(this);
   })
  });
  
4. Assign the class="greyonhover" for the image you want to implement grayscale effect onhover
<img class="greyonhover" src="images/naveenj-thumb.jpg" />
  

This is all you have to do to achieve greying effect on hover. Download Source Code(9k)
Read more...

Wednesday, October 21, 2009

Selectable GridViewRow using Javascript

0 comments
Hope you have read my post about Selectable GridViewRow
If you haven't done that please do that before you proceed further.
This is a sort of sequel to that post.

Here I am making a GridView Selectable using __doPostBack(...) function

Suppose you have a GridView populated from the Products table of the NorthWind Database.

So the ASPX looks like this

<asp:GridView ID="gvwProducts" runat="server"
AutoGenerateColumns="False" 
DataKeyNames="ProductID"
DataSourceID="sdsProducts"
OnRowDataBound="gvwProducts_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Contact Name">
<ItemTemplate>
<asp:Label ID="lblProductName" runat="server"
Text='<%#Eval("ProductName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Stock">
<ItemTemplate>
<asp:Label ID="lblunitsInStock" runat="server"
Text='<%#Eval("UnitsInStock") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>

</Columns>
<SelectedRowStyle ForeColor="Green" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server" 
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT ProductID, ProductName, UnitsInStock FROM Products"
SelectCommandType="Text">
</asp:SqlDataSource>



Now on RowDataBound lets set the click attribute for selectable row.
You can also use RowCreated for this.
Note that we are also giving some fancy color changes in onmouseover and onmouseout events.
Discard them if you dont want color changes.

protected void gvwProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
//e.Row.Attributes["onmouseover"] = "this.style.color='DodgerBlue';this.style.cursor='hand';";
e.Row.Attributes["onmouseover"] = "javascript:return ChangeRowColor('m_over', this.style)";
//e.Row.Attributes["onmouseout"] = "this.style.color='Black';";
e.Row.Attributes["onmouseout"] = "javascript:return ChangeRowColor('m_out', this.style)";
e.Row.Attributes["onclick"] = "javascript:return __doPostBack('" + gvwProducts.ClientID.Replace('_','$') + "', 'Select$" + e.Row.RowIndex + "');";
e.Row.ToolTip = "Click on the row to select it";
}
}



Now register these postbacks for event validation at Page_Render to avoid



System.ArgumentException: Invalid postback or callback argument. Event validation is enabled using in configuration or <%@ Page EnableEventValidation="true" %> in a page. For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them. If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation



protected override void Render(HtmlTextWriter writer)
{
// .NET will refuse to accept "unknown" postbacks for security reasons. 
// Because of this we have to register all possible callbacks
// This must be done in Render, hence the override
for (int i = 0; i < gvwProducts.Rows.Count; i++)
{
Page.ClientScript.RegisterForEventValidation(new System.Web.UI.PostBackOptions(this.gvwProducts, "Select$" + i.ToString()));
}
// Do the standard rendering stuff
base.Render(writer);
}

Now compare the RowDataBound event to first example and you note some changes in the way the row attributes for onmouseover and onmouseout are set. (Check the commented lines in the RowDataBound event) What we do here is to set a foreground color "Green" to the Selected Row and persists that color onmouseout and onmouseover of the selected row. Inorder to achieve that, place this javascript function on the page.
function ChangeRowColor(eventtype, rowStyle){
if(rowStyle.color.toLowerCase() != "green"){
if(eventtype == "m_over"){
rowStyle.color='DodgerBlue';
rowStyle.cursor='pointer';
}
else{
rowStyle.color='Black';
}
}
else{
rowStyle.cursor='default';
}
}

Now some developers may get the
__doPostBack(...) object required
To circumvent this error place these on the ASPX Page Two Hidden Fields
<input type ="hidden" name ="__EVENTTARGET" value ="" />
<input type ="hidden" name ="__EVENTARGUMENT" value ="" />

Javascript Function
//



Happy Coding!
Read more...

Monday, October 19, 2009

Selectable GridViewRow

1 comments
I have always found using Select Button in GridView to select a row cumbersome.
It would be always better to click anywhere on the GridViewRow and Select the row.

Here's a snippet on how to do it.

On RowDataBound

protected void gvwProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{

e.Row.Attributes["onmouseover"] = "this.style.color='DodgerBlue';this.style.cursor='hand';";
e.Row.Attributes["onmouseout"] = "this.style.color='Black';";
e.Row.Attributes["onclick"] = ClientScript.GetPostBackClientHyperlink(this.gvwProducts, "Select$" + e.Row.RowIndex);
e.Row.ToolTip = "Click on the row to select it";
}
}


Now if we run the code and click on the row we will get this error



System.ArgumentException: Invalid postback or callback argument.
Event validation is enabled using in configuration
or <%@ Page EnableEventValidation="true" %> in a page.
For security purposes, this feature verifies that arguments to postback or callback events originate
from the server control that originally rendered them.
If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method
in order to register the postback or callback data for validation.



To avoid this we override the Page's Render Event.
Inside that event we register an event reference for validation on each GridViewRow

The overridden Page Render

protected override void Render(HtmlTextWriter writer)
{
// .NET will refuse to accept "unknown" postbacks for security reasons. 
// Because of this we have to register all possible callbacks
// This must be done in Render, hence the override
for (int i = 0; i < gvwProducts.Rows.Count; i++)
{
Page.ClientScript.RegisterForEventValidation(new System.Web.UI.PostBackOptions(gvwProducts, "Select$" + i.ToString()));
}
// Do the standard rendering stuff
base.Render(writer);
}
Here I am posting the ASPX markup of the GridView also The ASPX
<asp:GridView ID="gvwProducts" runat="server"
AutoGenerateColumns="False" 
DataKeyNames="ProductID"
DataSourceID="sdsProducts"
OnRowDataBound="gvwProducts_RowDataBound">
<Columns>
<asp:TemplateField HeaderText="Contact Name">
<ItemTemplate>
<asp:Label ID="lblProductName" runat="server"
Text='<%#Eval("ProductName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Stock">
<ItemTemplate>
<asp:Label ID="lblunitsInStock" runat="server"
Text='<%#Eval("UnitsInStock") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>

</Columns>
<SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />
<HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server" 
ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
SelectCommand="SELECT ProductID, ProductName, UnitsInStock FROM Products"
SelectCommandType="Text">
</asp:SqlDataSource>
Just paste the last xml snippet on ASPX and first two code snippets on cs page. Change the connectionstring to the one you have and run the code to see the result. We are not finished yet From time to time, some developers will experience the "__doPostBack object expected" error in the page Postback. This occurs at the second time we try to fire the row click event The Reason
We add onclick feature for GridView in the RowDataBound event using ClientScript.GetPostBackClientHyperlink(...) But RowDataBound event gets fired only the first time(at !IsPostBack). This creates the __doPostBack() function when the page is first time loaded. Now from the second time onwards(at IsPostBack) RowDataBound doesn't get fired. So no ClientScript.GetPostBackClientHyperlink(...) is called and no __doPostBack() function is created
The solution. Just place this line under Page_Load event
protected void Page_Load(object sender, EventArgs e)
{
ClientScript.GetPostBackClientHyperlink(this, "");
}

Happy Coding! For Better understanding please read Selectable GridViewRow using JavaScript Points to Note: 1. I have given a SelectedRowStyle to show that the row is actually selected by giving it a different color. 2. The table used is Products from Microsoft's Sample DataBase Northwind
Read more...

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...

Wednesday, March 25, 2009

Paging a Filtered GridView

0 comments
In many forums there are people struggling with filtering and paging in gridview.
When separated, both filtering and paging works smoothly.
But when trying to change the page index of a filtered result set, all hell will break loose.
Mostly a new page with the unfiltered result set comes into play.


Here's a sample on how to do it.


The ASPX



<table>
<tr>
<td>
Search By Product Name:
</td>
<td>
<asp:TextBox ID="txtProductName" runat="server"></asp:TextBox>
</td>
<td>
<asp:Button ID="btnBindGridView" runat="server"
Text="Populate Grid" onclick="btnBindGridView_Click" />
</td>
</tr>
<tr>
<td colspan="3">
<asp:GridView ID="gvwProducts" runat="server"
AllowPaging="true"
AutoGenerateColumns="false"
PageSize="3"
OnPageIndexChanging="gvwProducts_PageIndexChanging">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product Name"/>
<asp:BoundField DataField="QuantityPerUnit" HeaderText="Quantity"/>
<asp:BoundField DataField="UnitPrice" HeaderText="Price"/>
</Columns>
</asp:GridView>
</td>
</tr>
</table>



The ASPX.CS



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

protected void btnBindGridView_Click(object sender, EventArgs e)
{
BindGridView();
}

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

private void BindGridView()
{
DataTable dtProducts = new DataTable();
string strSelectCommand = "SELECT * FROM Products"
+ ((txtProductName.Text.Trim() == "") ? "" : (" WHERE ProductName LIKE '" + txtProductName.Text.Trim() + "%'"));
using (SqlConnection sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString))
{
using (SqlDataAdapter adapProducts = new SqlDataAdapter(strSelectCommand, sqlConn))
{
adapProducts.Fill(dtProducts);
}
}
gvwProducts.DataSource = dtProducts;
gvwProducts.DataBind();
}



DataBase used --> Northwind
Extra Namespace used -->System.Data.SqlClient;

Hope this helps!
Read more...

Monday, March 16, 2009

Filtered GridView using DataList

1 comments
Many times the requirement comes like this.

need to show the first letter of products as a link outside grid and when the user clicks on it the grid will be showing the result with that particular product only.


Can be easily done using GridView and DataList.
Database used is Northwind.

The ASPX



<asp:DataList ID="dlstProducts" runat="server"
RepeatDirection="Horizontal">
<ItemTemplate>
<asp:LinkButton ID="lnkFirstLetters" runat="server"
Text='<%# Bind("ProductNameFirstLetter") %>'
onclick="lnkFirstLetters_Click">
</asp:LinkButton>
</ItemTemplate>
</asp:DataList>

<asp:GridView ID="gvwProducts" runat="server"
AutoGenerateColumns="false"
DataKeyNames="ProductID">
<Columns>
<asp:TemplateField HeaderText="Product Name">
<ItemTemplate>
<asp:Label ID="lblProductName" runat="server" Text='<%# Bind("ProductName") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Quantity Per Unit">
<ItemTemplate>
<asp:Label ID="lblQuantityPerUnit" runat="server" Text='<%# Bind("QuantityPerUnit") %>'>
</asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>



The ASPX.CS



public partial class GridView_GridViewDataListFirstAlphabet : System.Web.UI.Page
{
DataTable dtProducts = new DataTable();

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

protected void lnkFirstLetters_Click(object sender, EventArgs e)
{
BindGridView(((LinkButton)sender).Text.Trim());
}

private void InitialBindOfControls()
{
BindGridView("Initial");
BindDataList();
}

private void BindGridView(string strChar)
{
string strQuery = "SELECT ProductID, ProductName, QuantityPerUnit FROM Products "
+ ((strChar == "Initial") ? "" : "WHERE ProductName LIKE'" + strChar + "%'")
+ "ORDER BY ProductName";
using (SqlConnection sqlConn = new SqlConnection(ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ToString()))
{
using (SqlDataAdapter adapProducts = new SqlDataAdapter(strQuery, sqlConn))
{
adapProducts.Fill(dtProducts);
gvwProducts.DataSource = dtProducts;
gvwProducts.DataBind();
}
}
}

private void BindDataList()
{
if (gvwProducts.Rows.Count != 0)
{
DataTable dtTemp = new DataTable();
dtTemp.Columns.Add("ProductNameFirstLetter");
dtTemp.Rows.Add(((Label)gvwProducts.Rows[0].FindControl("lblProductName")).Text.Substring(0, 1));
foreach (GridViewRow gvrProducts in gvwProducts.Rows)
{
if (dtTemp.Rows[dtTemp.Rows.Count - 1][0].ToString() != ((Label)gvrProducts.FindControl("lblProductName")).Text.Substring(0, 1))
{
dtTemp.Rows.Add(((Label)gvrProducts.FindControl("lblProductName")).Text.Substring(0, 1));
}
}
dlstProducts.DataSource = dtTemp;
dlstProducts.DataBind();
}
}
}



Extra Namespace used


using System.Data.SqlClient;

Read more...

Monday, February 2, 2009

Maintaining State of CheckBox while Paging in GridView

0 comments
The Logic
We are storing the primary keys of the checkboxes that are checked into a List where T = data type of the primary key. This is done at PageIndexChanging before we change the page index and re-bind the GridView. And at RowDataBound we are checking whether the DataKeyName(primary key) of each row is in the List. If present , we mark the CheckBox as checked.
Heres the sample code.

The ASPX

<asp:LinkButton ID="btnSelectAllPage" runat="server" 
            CommandName="SelectAllPage" 
            Text="Select All Pages"
            OnCommand="SelectDeselectAllPages" />|
<asp:LinkButton ID="btnDeselectAllPage" runat="server" 
            CommandName="DeselectAllPage" 
            Text="Deselect All Pages"
            OnCommand="SelectDeselectAllPages" />|
<asp:LinkButton ID="btnSelectAll" runat="server" 
            CommandName="SelectAll" 
            Text="Select Page"
            OnCommand="SelectDeselect" />|
<asp:LinkButton ID="btnDeselectAll" runat="server" 
            CommandName="DeselectAll" 
            Text="Deselect Page"
            OnCommand="SelectDeselect" />

<asp:GridView ID="gvProducts" runat="server" 
            AllowPaging="True" 
            AutoGenerateColumns="False"
            DataKeyNames="ProductID"
            OnPageIndexChanging="gvProducts_PageIndexChanging" 
            OnRowDataBound="gvProducts_RowDataBound">
    <Columns>
        <asp:TemplateField HeaderText="Select">
            <ItemTemplate>
                <asp:CheckBox ID="chkSelect" runat="server" />
            </ItemTemplate>
        </asp:TemplateField>
    <asp:BoundField DataField="ProductID" HeaderText="ProductID" InsertVisible="False"
    ReadOnly="True" SortExpression="ProductID" />
    <asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server"
                ConnectionString='<%$ ConnectionStrings:NorthwindConnectionString %>'
                SelectCommand="SELECT * FROM Products">
</asp:SqlDataSource>



The ASPX.CS

private List<int> ProductIDs
{
    get
    {
        if (this.ViewState["ProductIDs"] == null)
        {
            this.ViewState["ProductIDs"] = new List<int>();
        }
        return this.ViewState["ProductIDs"] as List<int>;
    }
}

protected void SelectDeselect(object sender, CommandEventArgs e)
{
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            chkSelect.Checked = e.CommandName.Equals("SelectAll");
        }
    }
}

protected void SelectDeselectAllPages(object sender, CommandEventArgs e)
{
    DataSourceSelectArguments dssa = new DataSourceSelectArguments();
    dssa.AddSupportedCapabilities(DataSourceCapabilities.RetrieveTotalRowCount);
    dssa.RetrieveTotalRowCount = true;
    DataView dv = (DataView)sdsProducts.Select(dssa);
    foreach (DataRow dr in dv.Table.Rows)
    {

        int productID = Convert.ToInt32(dr.ItemArray[0]);//ItemArray[0] cos ProductID is in the first column
        if (e.CommandName.Equals("SelectAllPage") && !this.ProductIDs.Contains(productID))
        {
            this.ProductIDs.Add(productID);
        }
        if (e.CommandName.Equals("DeselectAllPage") && this.ProductIDs.Contains(productID))
        {
            this.ProductIDs.Remove(productID);
        }
    }
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            chkSelect.Checked = e.CommandName.Equals("SelectAllPage");
        }
    }
}

protected void gvProducts_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
    foreach (GridViewRow gvr in gvProducts.Rows)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            if (chkSelect.Checked && !this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Add(productID);
            }
            else if (!chkSelect.Checked && this.ProductIDs.Contains(productID))
            {
                this.ProductIDs.Remove(productID);
            }
        }
    }
}

protected void gvProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
    GridViewRow gvr = e.Row;
    if (gvr.RowType == DataControlRowType.DataRow)
    {
        CheckBox chkSelect = gvr.FindControl("chkSelect") as CheckBox;
        if (chkSelect != null)
        {
            int productID = Convert.ToInt32(gvProducts.DataKeys[gvr.RowIndex]["ProductID"]);
            chkSelect.Checked = this.ProductIDs.Contains(productID);
        }
    }
}

As an extra enhancement, we are also giving provision for selecting, deselecting both page and the whole rows in every page also here.

P.S: We are using Northwind Sample DataBase by Microsoft, so if you dont have it download it.

Courtesy: A wonderful post by Ed Bruck at forums.asp.net
Read more...

Sunday, February 1, 2009

Insert Custom Advertisement Row in GridView

3 comments
Inserting advertisements between,say every tenth row populated by a gridview


The ASPX

<asp:GridView ID="GridView1" runat="server"  
AutoGenerateColumns="False"  
Height="171px" 
DataSourceID="sdsProducts"
Width="189px" 
OnRowDataBound="GridView1_RowDataBound">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"/>
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="sdsProducts" runat="server" 
ConnectionString='<%$ ConnectionStrings:NorthwindConnectionString %>'
SelectCommand="SELECT * FROM Products">
</asp:SqlDataSource>

The ASPX.CS
protected void GridView1_RowDataBound(object sender, System.Web.UI.WebControls.GridViewRowEventArgs e)
{
if (e.Row.DataItem != null)
{
int intCurrentId = e.Row.RowIndex;
if ((intCurrentId + 1) % 10 == 0)
{
// Add a row before this record
Table tblGrid = (Table)this.GridView1.Controls[0];
// Get the rowindex of the current row
int intIndex = tblGrid.Rows.GetRowIndex(e.Row);
// Create a new row to hold our subheading
GridViewRow gvrSubHeading = new GridViewRow(intIndex, intIndex, DataControlRowType.Separator, DataControlRowState.Normal);
// Create a table cell for the row
TableCell cellHeader = new TableCell();
// Set the colspan of the cell to the width of the table
cellHeader.ColumnSpan = this.GridView1.Columns.Count;
// Set the text
cellHeader.Text = "Your Advertisement goes here";
// Add the cell to the row
gvrSubHeading.Cells.Add(cellHeader);
// Add the row to the table
tblGrid.Controls.AddAt(intIndex + 1, gvrSubHeading);
}
}

}

Thats all.

P.S: The DataBase used is Northwind

Courtesy : Samu Zhang - MSFT of http://forums.asp.net
The original VB version posted by Samu Zhang can be found here
Read more...