Monday, March 24, 2008

GridView Alphabet Paging

Introduction:

GridView paging feature allow us to display fixed number of records on the page and browse to the next page of records. Although paging is a great feature but sometimes we need to view all the items alphabetically. The idea behind this article is to provide a user with a list of all the alphabets and when the user clicks on a certain alphabet then all the records starting with that alphabet will be populated in the GridView control.

Populating the GridView Control:

The first task is to populate the GridView control. I will be using the Northwind database in my article which, is installed by default for SQL SERVER 2000 and SQL SERVER 7 databases. The code below is used to populate the GridView control.

private void BindData()
{
string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=true";
SqlConnection myConnection = new SqlConnection(connectionString);
SqlDataAdapter ad = new SqlDataAdapter("SELECT ProductID, ProductName FROM Products", myConnection);

DataSet ds = new DataSet();
ad.Fill(ds);

gvCategories.DataSource = ds;
gvCategories.DataBind();
}

Creating the Alphabetical List:

The next task is to create an alphabetical list and display it in the GridView control. The best place to display the list is the GridView footer. Let’s check out the code which is used to create the list.

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

TableCell cell = e.Row.Cells[0];
cell.ColumnSpan = 2;

for (int i = 65; i <= (65 + 25); i++)
{
LinkButton lb = new LinkButton();

lb.Text = Char.ConvertFromUtf32(i) + " ";
lb.CommandArgument = Char.ConvertFromUtf32(i);
lb.CommandName = "AlphaPaging";

cell.Controls.Add(lb);

}
}
}

The RowCreated event is used to create the list. In the event first I check for the footer row. Once, the footer row is found I run a loop from 65 to 92 and convert each number into the character representation. The number 65 stands for “A”, 66 for “B” and so on till 92 for “Z”. Inside the loop I created LinkButton and set the Text property to the alphabet. Finally, the control is added to the cell collection.

Fetching the Records Based on the Alphabet:

In the last section we created the alphabets and displayed them in the footer of the GridView control. The next task is to capture the event generated by the alphabets when we click on them and fetch the results based on the alphabet. The RowCommand event is fired whenever you click on any alphabet. Take a look at the RowCommand event below:

protected void gvCategories_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName.Equals("AlphaPaging"))
{
string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=true";
string selectQuery = "SELECT ProductID, ProductName FROM Products WHERE ProductName LIKE '" + e.CommandArgument + "%'";

SqlConnection myConnection = new SqlConnection(connectionString);

SqlDataAdapter ad = new SqlDataAdapter(selectQuery,myConnection);

DataSet ds = new DataSet();
ad.Fill(ds);

gvCategories.DataSource = ds;
gvCategories.DataBind();
}
}

At first I check that if the CommandName is “AlphaPaging”. This check is made since RowCommand handles all the events generated inside the GridView control. Next, I used the T-SQL LIKE operator to fetch the results from the database and populate the results in the GridView control.

DHTML ToolTip with Calendar Control

Introduction:

In one of my previous articles I talked about how you can effectively use DHTML with Asp.net to make cool tooltip. In this article I will show how you can use the same DHTML tooltip with the calendar control.

Getting Started:

The first thing you need to do is to download the DHTML script from www.dynamicdrive.com. You can download the script from this url http://www.dynamicdrive.com/dynamicindex5/dhtmltooltip.htm. After download the script just place the required css in the head section of the page and the script in the body of the page.

Screen shot of what we are going to do:

Here is a screen shot of what we are going to do in this article. As you can see that when you place your cursor over any date in the calendar it pops out the description in the DHTML box.

The Code:

The code is pretty simple. First you need to pull all the information from the database to your dataset or any other collection.

private DataSet GetArticles()

{

string connectionString = @"Server=localhost;Database=GridViewGuy;Trusted_Connection=true";

SqlConnection myConnection = new SqlConnection(connectionString);

SqlDataAdapter ad = new SqlDataAdapter("SELECT TOP 10 ArticleID,Title,Description,Abstract,DateCreated FROM Articles ORDER BY DateCreated DESC", myConnection);

DataSet ds = new DataSet();

ad.Fill(ds, "Articles");

return ds;

}

Next to display this information in the Calendar boxes you need to implement the Day_Render event of the Calendar Control.

protected void Calendar1_DayRender(object sender, DayRenderEventArgs e)

{

DataSet d = GetArticles();

foreach(DataRow dr in d.Tables[0].Rows) {

string dt = ((DateTime) dr["DateCreated"]).ToShortDateString();

if (dt == e.Day.Date.ToShortDateString())

{

e.Cell.Text = dr["Title"] as String;

}

}

string title = e.Cell.Text;

string ab = String.Empty;

foreach (DataRow dr in d.Tables[0].Rows)

{

if (title == dr["Title"] as String)

{

ab = dr["Abstract"] as String;

}

}

string dhtmlBox = "ddrivetip('" + ab + "','lightyellow','200')";

e.Cell.Attributes["onmouseover"] = dhtmlBox;

e.Cell.Attributes["onmouseout"] = "this.style.backgroundColor='#C0C000';";

}

All I am doing is I fill the Calendar cells using the e.Cell.Text property with the title of the article. And since I got everything I need thing I need in the dataset I simply browse the database for the particular description of the article and pops it up in the DTHML tooltip.

Creating the CAPTCHA Functionality

Introduction:

According to wikipedia, CAPTCHA ("Completely Automated Public Turing test to tell Computers and Humans Apart") is a challenge response test which is used to check that if the user is human or not. CAPTCHA is used exclusively in applications where the user input is required. These applications include Blogs, Forums and Portals. In this article I will demonstrate how to create a simple webpage that uses CAPTCHA functionality.

The CreateImage Method:

The first task is to create an image and put it on the screen. For that I have created an ASP.NET page named CaptchaControl.aspx. The CaptchaControl.aspx page will be responsible for displaying the image to the user. Let’s take a look at the following code which generates the image.

private void CreateImage()

{

string code = GetRandomText();

Bitmap bitmap = new Bitmap(200,150,System.Drawing.Imaging.PixelFormat.Format32bppArgb);

Graphics g = Graphics.FromImage(bitmap);

Pen pen = new Pen(Color.Yellow);

Rectangle rect = new Rectangle(0,0,200,150);

SolidBrush b = new SolidBrush(Color.DarkKhaki);

SolidBrush blue = new SolidBrush(Color.Blue);

int counter = 0;

g.DrawRectangle(pen, rect);

g.FillRectangle(b, rect);

for (int i = 0; i <>

{

g.DrawString(code[i].ToString(), new Font("Verdena", 10 + rand.Next(14, 18)), blue, new PointF(10 + counter, 10));

counter += 20;

}

DrawRandomLines(g);

Response.ContentType = "image/gif";

bitmap.Save(Response.OutputStream,ImageFormat.Gif);

g.Dispose();

bitmap.Dispose();

}

There is a bunch of stuff going on inside the CreateImage method. The GetRandomText method generates the random text and returns to the caller. If you are unfamiliar with creating random strings then I would suggest that you check out my article Creating Random Password. After I created the Rectangle where the text would appear I resized the text to give it a strange look. Finally, I called the DrawRandomLines method which protects the image from OCR softwares.

The GetRandomText Method:

The purpose of the GetRandomText method is to generate a random text every time a user gets the old text wrong. Take a look at the simple method which returns the random text.

private string GetRandomText()

{

StringBuilder randomText = new StringBuilder();

if (Session["Code"] == null)

{

string alphabets = "abcdefghijklmnopqrstuvwxyz";

Random r = new Random();

for (int j = 0; j <= 5; j++)

{

randomText.Append(alphabets[r.Next(alphabets.Length)]);

}

Session["Code"] = randomText.ToString();

}

return Session["Code"] as String;

}

The DrawRandomLines Method:

The DrawRandomLines method puts the lines on the text which, are displayed on an image. The purpose of these lines is to make it difficult for the bots to read the text. This way the text can only be read by humans.

private void DrawRandomLines(Graphics g)

{

SolidBrush green = new SolidBrush(Color.Green);

for (int i = 0; i <>

{

g.DrawLines(new Pen(green, 2), GetRandomPoints());

}

}

private Point[] GetRandomPoints()

{

Point[] points = { new Point(rand.Next(10, 150), rand.Next(10, 150)), new Point(rand.Next(10, 100), rand.Next(10, 100)) };

return points;

}

Using the CAPTCHA Page:

We have created the CAPTCHA feature but the question is how do we use it. In order to use the CAPTCHA feature you will need to create a page which consumes the CaptchaControl.aspx page. I have created the Default.aspx page which uses the CaptchaControl.aspx as the ImageUrl to the ASP.NET image control. Check out the complete HTML code of the Default.aspx page.

<form id="form1" runat="server">

<div>

<asp:Image ID="myImage" runat="server" ImageUrl="~/CaptchaControl.aspx" />

<br />

<br />

Enter code: <asp:TextBox ID="TextBox1" runat="server">asp:TextBox>

<asp:Button ID="Button1" runat="server" Text="Validate" OnClick="Button1_Click" />

<br />

<br />

<asp:Label ID="lblError" runat="server" Font-Bold="True" Font-Size="X-Large" ForeColor="Red">asp:Label>div>

form>

The important thing to note is the ASP.NET image control which, requests the CaptchaControl.aspx

page and generates the image. The code for the validation of the user text against the CAPTCHA text is pretty simple and you can view it in the downloaded files.


Displaying Hierarchical Data in the DropDownList


Introduction:


Most of the web applications display hierarchical data. There are numerous ways for presenting the hierarchical data in which, most common is to use the Tree control. Although, the Tree control serves a good purpose for displaying the hierarchical data but in some scenarios we have to find an alternative solution. In this article I will demonstrate how you can use a simple ASP.NET DropDownList control to display hierarchical data.


Database and Stored Procedure:


In this article I will be using the Northwind database which, is installed by default for SQL SERVER 7 and SQL SERVER 2000 databases. I have added a new stored procedure which returns multiple record sets. The first record set contains the categories and the second one contains the products.



Populating the DropDownList:


The next step is to populate the DropDownList with the data from the Northwind database. For, this purpose I have created a BindData method which retrieves the data from the database and populate the DropDownList. Take a look at the BindData method below:

private void BindData()

{

string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=true";

SqlConnection myConnection = new SqlConnection(connectionString);

SqlCommand myCommand = new SqlCommand("usp_GetProductsForCategories", myConnection);

myCommand.CommandType = CommandType.StoredProcedure;

SqlDataAdapter ad = new SqlDataAdapter(myCommand);

DataSet ds = new DataSet();

ad.Fill(ds);

foreach (DataRow row in ds.Tables[0].Rows)

{

int categoryID = Convert.ToInt32(row["CategoryID"]);

string categoryName = row["CategoryName"] as String;

ddlCategories.Items.Add(new ListItem(String.Empty, String.Empty));

ddlCategories.Items.Add(new ListItem(categoryName, "0"));

ddlCategories.Items.Add(new ListItem(String.Empty, String.Empty));

DataRow[] childRows = ds.Tables[1].Select("CategoryID = " + categoryID);

foreach (DataRow childRow in childRows)

{

ddlCategories.Items.Add(new ListItem((string)childRow["ProductName"], (childRow["ProductID"].ToString())));

}

}

// bind the dropdownlist

ddlCategories.Items[0].Text = "Please select a product";

ddlCategories.Items[0].Value = "Please select a product";

ddlCategories.DataBind();

}

Let’s see what is going on in the BindData method. First I make a connection to the database and populate the DataSet using the stored procedure usp_GetProductsForCategories. Since, the stored procedure returns multiple result sets the DataSet also contains multiple DataTables. The DataTable at index “0” contains the Categories table and the DataTable at index “1” contains the Products table.

Next, we use a foreach loop to iterate through the tables and populate the DropDownList. There are two very important points to note here. First, we are assigning the value “0” to the value of the Category ListItem. This is because we don’t need the Category value as we are only interested in the Product value. Second, is that we are adding empty ListItem objects to the DropDownList items collection. This is to add the space and to make the display better.

The last two lines simply assign the text “Please select a product” to the first item of the DropDownList control. If you run the sample you will see the following output.


Adding the Style:


Although the display looks okay but, it is hard to know that which ones are Categories and which ones are Products. Let’s see how we can make it look much better by adding some custom styles.

private void AddStyle()

{

foreach (ListItem item in ddlCategories.Items)

{

if (item.Value.Equals("0"))

{

item.Attributes.Add("class", "categoryItemStyle");

}

}

}

The AddStyle() method is called each time the page is loaded and adds the style to the Category ListItem in the DropDownList. The “0” value indicates that the ListItem is of Category type and not Product type. The effect is shown below:


Getting the Selected Product:


The last part is to find out that which product has been selected. This is pretty simple as we only need to check the condition that the selected value of the DropDownList is not empty or null and not “0”.

protected void Button1_Click(object sender, EventArgs e)

{

string selectedValue = String.Empty;

if (Page.IsValid)

{

selectedValue = ddlCategories.SelectedValue;

if (!String.IsNullOrEmpty(selectedValue) && selectedValue.Equals("0") == false)

{

lblMessage.Text = "Product is selected";

}

else

{

lblMessage.Text = "Please select a product";

}

}

}


Conclusion:


In this article I demonstrated how to display data from multiple tables into the DropDownList in a hierarchical format.


Bread Crumbs in ASP.NET 2.0

Introduction:

Bread Crumbs are not considered a good appetizer but it is a valuable feature introduced in ASP.NET 2.0. Bread Crumbs allows you to view your current location in the website. This means if you are in the horror movies section of the website then it will indicate that you are indeed in the horror movies section by presenting the hierarchical view of your position. By using Bread Crumbs you can navigate back and forth in the categories. In this article I will demonstrate that how you can use a Bread Crumb in your web application.

Understanding the Scenario:

Let's first understand the scenario before talking about the implementation of the application. Suppose you are building a website that will contain information about movies and books. Each of the category can have sub categories. Movies can be comedy or horror and books can be fiction or horror. In your application you might have different folders for each of the category. Take a look at the screen shot below which shows the folders layout for the application.

As, you can see that the books folder (Books) contains the fiction and horror folders. Similarly the Movies folder contains the comedy and horror folder and each of the category has its own web form. This hierarchy is reflected in the Web.sitemap file.

Web.SiteMap File:

Take a look at the Web.sitemap file which shows the hierarchy of the files and folders.

version="1.0" encoding="utf-8" ?>

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

<siteMapNode url="~/Default.aspx" title="Home" description="">

<siteMapNode url="~/Books/Default.aspx" title="Books" description="">

<siteMapNode url="~/Books/Fiction/FictionBooks.aspx" title="Fiction" />

<siteMapNode url="~/Books/Horror/HorrorBooks.aspx" title="Horror" />

siteMapNode>

<siteMapNode url="~/Movies/Default.aspx" title="Movies" >

<siteMapNode url="~/Movies/Comedy/ComedyMovies.aspx" title="Comedy Movies" />

<siteMapNode url="~/Movies/Horror/HorrorMovies.aspx" title="Horror Movies" />

siteMapNode>

siteMapNode>

siteMap>

Once, you have the sitemap file ready you need to create a navigation system for the user. ASP.NET 2.0 provides three new navigation controls namely TreeView, Menu and SiteMapPath. The SiteMapPath navigation works in a different way since you need to be on the page in order to see the previous pages. I will use the TreeView in this article and populate it using the Web.sitemap file.

Populating the TreeView Control with Web.SiteMap:

Since, the navigation will be displayed on most of the pages of the application it is a good idea to place it inside the Master Page. Take a look at the code below which shows how to populate the TreeView control with the data from the Web.sitemap.

<asp:TreeView ID="tvMenu" DataSourceID="SiteMapDataSource1" runat="server" BackColor="PeachPuff" BorderColor="#C0C000" ImageSet="Arrows">

<ParentNodeStyle Font-Bold="False" />

<HoverNodeStyle Font-Underline="True" ForeColor="#5555DD" />

<SelectedNodeStyle Font-Underline="True" ForeColor="#5555DD" HorizontalPadding="0px"

VerticalPadding="0px" />

<NodeStyle Font-Names="Tahoma" Font-Size="10pt" ForeColor="Black" HorizontalPadding="5px"

NodeSpacing="0px" VerticalPadding="0px" />

asp:TreeView>

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" />




Displaying the Bread Crumbs Using SiteMapPath Control:

Finally, we need to display the Bread Crumbs on the page. Displaying Bread Crumbs is pretty simple if you use the SiteMapPath control. Simply, place a SiteMapPath control on the master page and set its properties as follows:

<asp:SiteMapPath ID="SiteMapPath1" runat="server">

<RootNodeTemplate>

<asp:HyperLink ID="hlRoot" runat="server" Text='<%# Eval("title") %>' NavigateUrl='<%# Eval("url") %>' />

RootNodeTemplate>

<CurrentNodeTemplate>

<asp:HyperLink ID="hlCurrentNodeTemplate" runat="server" Text='<%# Eval("title") %>' NavigateUrl='<%# Eval("url") %>' />

CurrentNodeTemplate>

asp:SiteMapPath>

There are different types of templates available for the SiteMapPath control. I have demonstrated the RootNodeTemplate and the CurrentNodeTemplate. The RootNodeTemplate allows you to define the root of the Bread Crumb and the CurrentNodeTemplate allows you to define the currently active node of the Bread Crumb.

Take a look at the effect of the Bread Crumbs in the screen shots below: