Filtering the DataGrid...
In this article we will filter the DataGrid on two columns. This adds a little code complexity but is not
really very hard to do.
By: John Kilgo
Date: June 1, 2003
Download the code.
In the example for this article we will use the Products table from the Northwind database. We will also access
the Categories table in order to populate one of our two DropDownLists. We will be able to select a category from
a DropDownList and have a DataGrid change to show only products from that category. The Products table contains
prices for each product. We will also be able to choose price ranges from a DropDownList and have the DataGrid
filter to show only products within the selected price range. We will use a DataView to accomplish this.
First we will take a look at the .aspx page DGFilter.aspx. It establishes the two DropDownLists as well as the
DataGrid. About the only the things you should take note of are in the two DropDownLists. Notice that we have
set AutoPostBack to True so that the grid will be filtered upon selection of one of the items in either of the
DropDownLists. Also notice that we have set up an event handler triggered by the OnSelectedIndexChanged
event. This is set to a subroutine in our code-behind file called ChangeFilter.
<%@ Page Language="vb" AutoEventWireup="false" Src="DGFilter.aspx.vb" Inherits="DGFilter"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>DGFilter</title>
<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
<meta name="CODE_LANGUAGE" content="Visual Basic 7.0">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<asp:Label ID="lblCategory" Text="Category: " Runat="server" />
<asp:DropDownList ID="ddlCategoryFilter"
AutoPostBack="True"
OnSelectedIndexChanged="ChangeFilter"
Runat="server" />
<asp:Label ID="lblPriceFilter" Text="Price: " Runat="server" />
<asp:DropDownList ID="ddlPriceFilter"
AutoPostBack="True"
OnSelectedIndexChanged="ChangeFilter"
Runat="server">
<asp:ListItem Value="0" Selected="True">All Prices</asp:ListItem>
<asp:ListItem Value="1"><= $20</asp:ListItem>
<asp:ListItem Value="2">$20.01 - $40.00</asp:ListItem>
<asp:ListItem Value="3">$40.01 - $60.00</asp:ListItem>
<asp:ListItem Value="4">$60.01 - $80.00</asp:ListItem>
<asp:ListItem Value="5">Over $80.00</asp:ListItem>
</asp:DropDownList>
<p></p>
<asp:DataGrid ID="dtgProducts"
Runat="server"
HeaderStyle-BackColor="IndianRed"
HeaderStyle-ForeColor="White"
HeaderStyle-Font-Name="Verdana"
HeaderStyle-Font-Size="10"
ItemStyle-BackColor="Gainsboro"
ItemStyle-Font-Name="Verdana"
ItemStyle-Font-Size="10"
CellPadding="4"
GridLines="Both" />
</form>
</body>
</html>
|
Now for the code-behind file, DGFilter.aspx.vb. This will be shown in two parts to ease explanation of its
various sections. In part one, below, notice that set the category filter equal to 1 (Beverages) and the
price filter to UniitPrice > 0 meaning all prices will be shown. This will be the default setting when the
program first opens up. In the Page_Load event we call FillCategoryDropDown (the next subroutine) which fills
the Category DropDownList with the various product categories. After that is the subroutine BindTheData which
connects to the database, fills a DataSet with the products table data, and then creates a DataView with
strCategoryFilter and strPriceFilter as the row filter. This is analagous to adding a WHERE clause reading
"WHERE CategoryID=1 AND UnitPrice>0" for the first pass through the data. As we see in part two of the code,
strCategoryFilter or strPriceFilter may change based upon selections made by the user from the DropDownLists.
Imports System.Data
Imports System.Data.SqlClient
Imports System.Configuration
Public Class DGFilter
Inherits System.Web.UI.Page
Public strCategoryFilter As String = "CategoryID=1"
Public strPriceFilter As String = "UnitPrice>0"
Public strSql As String
Protected ddlCategoryFilter As System.Web.UI.WebControls.DropDownList
Protected ddlPriceFilter As System.Web.UI.WebControls.DropDownList
Protected WithEvents lblCategory As System.Web.UI.WebControls.Label
Protected WithEvents lblPriceFilter As System.Web.UI.WebControls.Label
Protected dtgProducts As System.Web.UI.WebControls.DataGrid
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IsPostBack Then
FillCategoryDropDown()
BindTheData()
End If
End Sub
Sub FillCategoryDropDown()
Dim objConn As SqlConnection
objConn = New SqlConnection(ConfigurationSettings.AppSettings("NorthwindConnection"))
strSql = "Select CategoryName, CategoryID From Categories"
Dim objCmd As New SqlCommand(strSql, objConn)
Dim dataReader As SqlDataReader = Nothing
Try
objConn.Open()
dataReader = objCmd.ExecuteReader()
ddlCategoryFilter.DataSource = dataReader
ddlCategoryFilter.DataTextField = "CategoryName"
ddlCategoryFilter.DataValueField = "CategoryID"
ddlCategoryFilter.DataBind()
Catch exc As System.Exception
Response.Write(exc.ToString())
Finally
objConn.Dispose()
End Try
End Sub
Sub BindTheData()
Dim objConn As SqlConnection
objConn = New SqlConnection(ConfigurationSettings.AppSettings("NorthWindConnection"))
strSql = "Select ProductID, ProductName, CategoryID, UnitPrice From Products"
Try
Dim dataAdapter As New SqlDataAdapter(strSql, objConn)
Dim dataSet As New DataSet()
dataAdapter.Fill(dataSet, "Products")
Dim dvProducts As New DataView(dataSet.Tables("Products"))
dvProducts.RowFilter = strCategoryFilter & " AND " & strPriceFilter
dtgProducts.DataSource = dvProducts
dtgProducts.DataBind
Catch exc As System.Exception
Response.Write(exc.ToString())
Finally
objConn.Dispose()
End Try
End Sub
|
Part two of the code shown below contains the more interesting code as far as the subject of the article is
concerned. Remember that in the .aspx file we set up an event handler called ChangeFilter in both of the
DropDownLists. It is call everytime a selection is made in either DropDownList. Here in the code-behind file
ChangeFilter calls two additional routines, FilterByCategory and FilterByPrice, before rebinding the data. When
these two routines are called they are passed the SelectedItem.Value and SelectedItem.Text respectively from
the appropriate DropDownLists. FilterByCategory simply builds our filter string strCategoryFilter by appending
the CategoryID from the value chosen by the user from the category dropdown. FilterByPrice gets passed the
text value from its DropDownList and the UnitPrice "WHERE clause" (strPriceFilter) is set appropriately.
Sub ChangeFilter(Source As System.Object, e As System.EventArgs)
FilterByCategory(ddlCategoryFilter.SelectedItem.Value.ToString())
FilterByPrice(ddlPriceFilter.SelectedItem.Text.ToString())
BindTheData()
End Sub
Sub FilterByCategory(strCategory As String)
strCategoryFilter = "CategoryID=" & strCategory
End Sub
Sub FilterByPrice(strPriceRange As String)
Select Case strPriceRange
Case "All Prices"
strPriceFilter = "UnitPrice>0"
Case "<= $20"
strPriceFilter = "UnitPrice<=20"
Case "$20.01 - $40.00"
strPriceFilter = "UnitPrice>20 AND UnitPrice<=40"
Case "$40.01 - $60.00"
strPriceFilter = "UnitPrice>40 AND UnitPrice<=60"
Case "$60.01 - $80.00"
strPriceFilter = "UnitPrice>60 AND UnitPrice<=80"
Case "Over $80.00"
strPriceFilter = "UnitPrice>80"
End Select
End Sub
End Class
|
I hope you found this code concise enough to follow without much trouble. Essentially, we are passing the
Category's DropDownList value and the Price's DropDownList Text to routines which build strings containing our
filters (strCategoryFilter and strPriceFilter) which then get passed back to the BindTheData routine to be
incorporated in the DataView's row filter. Best of luck.
You may download the code here.