Filter with MS DropDownList Instead of Textbox
You can create a custom column class that replaces the filter text box with a drop-down list. This provides an alternate way for users to enter filter criteria. The drop down list can be configured so that it causes the grid to filter records when the user selects an item.
The following steps describe how to achieve this result:
- Create a custom column class that extends the default GridBoundColumn.
- In this custom column class, override the SetupFilterControls method to replace the filter text box and image button with a DropDownList control. Configure the DropDownList control as desired. At a minimum,
- Set the AutoPostBack property to True.
- Set the ID property to a unique value.
- Bind the items list.
- Add a SelectedIndexChanged event handler.
- Override the SetCurrentFilterValueToControl and GetCurrentFilterValueFromControl methods to set or get the SelectedValue of the drop-down list.
- In the SelectedIndexChanged event handler, get the GridFilteringItem of the grid and call its FireCommandEvent method to initiate a filter command.
Defining the custom column class
The following example illustrates how to create a custom column class that replaces the filter text box with a drop-down list.
C#
public class MyCustomFilteringColumn : GridBoundColumn
{
private object listDataSource = null;
//RadGrid calls this method when it initializes the controls inside the filtering item cells
protected override void SetupFilterControls(TableCell cell)
{
base.SetupFilterControls(cell);
cell.Controls.RemoveAt(0);
DropDownList list = new DropDownList();
list.ID = "list" + this.DataField;
list.AutoPostBack = true;
list.SelectedIndexChanged += new EventHandler(list_SelectedIndexChanged);
cell.Controls.AddAt(0, list);
cell.Controls.RemoveAt(1);
list.DataTextField = this.DataField;
list.DataValueField = this.DataField;
list.DataSource = this.ListDataSource;
}
void list_SelectedIndexChanged(object sender, EventArgs e)
{
GridFilteringItem filterItem = (sender as DropDownList).NamingContainer as GridFilteringItem;
if (this.DataType == System.Type.GetType("System.Int32") || this.DataType == System.Type.GetType("System.Int16") || this.DataType == System.Type.GetType("System.Int64"))
{
filterItem.FireCommandEvent("Filter", new Pair("EqualTo", this.UniqueName));
}
else
// treat everything else like a string
filterItem.FireCommandEvent("Filter", new Pair("Contains", this.UniqueName));
}
public object ListDataSource
{
get
{
return this.listDataSource;
}
set
{
listDataSource = value;
}
}
//RadGrid calls this method when the value should be set to the filtering input control(s)
protected override void SetCurrentFilterValueToControl(TableCell cell)
{
base.SetCurrentFilterValueToControl(cell);
DropDownList list = (DropDownList)cell.Controls[0];
if (this.CurrentFilterValue != string.Empty)
{
list.SelectedValue = this.CurrentFilterValue;
}
}
//RadGrid calls this method to extract the filtering value from the filtering input control(s)
protected override string GetCurrentFilterValueFromControl(TableCell cell)
{
DropDownList list = (DropDownList)cell.Controls[0];
return list.SelectedValue;
}
protected override string GetFilterDataField()
{
return this.DataField;
}
}
VB
Imports Microsoft.VisualBasic
Imports Telerik.Web.UI
Imports System.Collections
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Data
Namespace MyStuff
Public Class MyCustomFilteringColumn
Inherits GridBoundColumn
Private _listDataSource As Object = Nothing
Public Property ListDataSource() As Object
Get
Return _listDataSource
End Get
Set(ByVal value As Object)
_listDataSource = value
End Set
End Property
'RadGrid calls this method when it initializes the controls inside the filtering item cells
Protected Overloads Overrides Sub SetupFilterControls(ByVal cell As TableCell)
MyBase.SetupFilterControls(cell)
cell.Controls.RemoveAt(0)
Dim list As New DropDownList()
list.ID = "list" + Me.DataField
list.AutoPostBack = True
AddHandler list.SelectedIndexChanged, AddressOf list_SelectedIndexChanged
cell.Controls.AddAt(0, list)
cell.Controls.RemoveAt(1)
list.DataTextField = Me.DataField
list.DataValueField = Me.DataField
list.DataSource = _listDataSource
list.DataBind()
End Sub
Sub list_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim filterItem As GridFilteringItem = TryCast((TryCast(sender, DropDownList)).NamingContainer, GridFilteringItem)
If Me.DataType Is Type.GetType("System.Int32") OrElse Me.DataType Is Type.GetType("System.Int16") OrElse Me.DataType Is Type.GetType("System.Int64") Then
filterItem.FireCommandEvent("Filter", New Pair("EqualTo", Me.UniqueName))
Else
filterItem.FireCommandEvent("Filter", New Pair("Contains", Me.UniqueName))
' treat everything else like a string
End If
End Sub
'RadGrid calls this method when the value should be set to the filtering input control(s)
Protected Overloads Overrides Sub SetCurrentFilterValueToControl(ByVal cell As TableCell)
MyBase.SetCurrentFilterValueToControl(cell)
Dim list As DropDownList = DirectCast(cell.Controls(0), DropDownList)
If Me.CurrentFilterValue <> String.Empty Then
list.SelectedValue = Me.CurrentFilterValue
End If
End Sub
'RadGrid calls this method to extract the filtering value from the filtering input control(s)
Protected Overloads Overrides Function GetCurrentFilterValueFromControl(ByVal cell As TableCell) As String
Dim list As DropDownList = DirectCast(cell.Controls(0), DropDownList)
Return list.SelectedValue
End Function
Protected Overloads Overrides Function GetFilterDataField() As String
Return Me.DataField
End Function
End Class
End Namespace
Adding custom columns to a grid
You can add instances of your custom column type RadGrid as follows:
-
At the top of the the ASPX page, register the namespace for the custom column class. You do not need to add an Assembly attribute, unless the class is defined in another assembly:
ASP.NET
<%@ register namespace="MyStuff" tagprefix="custom" %>
-
You can now add instances of the column type in the declaration of your grid. Note that this example includes a command item with a "Clear" button to clear the selected filters:
ASP.NET
<telerik:RadGrid ID="RadGrid1" runat="server" AllowFilteringByColumn="True" AllowPaging="True" PageSize="5" DataSourceID="AccessDataSource1" OnItemCommand="RadGrid1_ItemCommand"> <MasterTableView AutoGenerateColumns="False" DataSourceID="AccessDataSource1" CommandItemDisplay="Top"> <CommandItemTemplate> <asp:LinkButton Runat="server" ID="LinkButton1" Text="Clear Filters" CommandName="ClearFilters" /> </CommandItemTemplate> <Columns> <custom:MyCustomFilteringColumn HeaderText="Employee ID" DataField="EmployeeID" UniqueName="EmployeeID" /> <custom:MyCustomFilteringColumn HeaderText="Customer ID" DataField="CustomerID" UniqueName="CustomerID" /> <telerik:GridBoundColumn AllowFiltering="False" HeaderText="Order ID" DataField="OrderID" UniqueName="OrderID" /> </Columns> </MasterTableView> </telerik:RadGrid> <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" SelectCommand="SELECT * FROM [Orders]"> </asp:SqlDataSource>
-
The MyCustomFilteringColumn implementation requires a ListDataSource. You can set that in the Page_Load event handler. In addition, the grid definition above requires an implementation for the "ClearFilters" button:
This example sets the ListDataSource property in the Page_Load event handler. If you are binding your grid using the NeedDataSource event, it is more appropriate to set the ListDataSource in that event handler. (NeedDataSource does not occur when using declarative data binding.)
C#
protected void Page_Load(object sender, EventArgs e) { foreach (GridBoundColumn column in RadGrid1.MasterTableView.Columns) { if (column is MyStuff.MyCustomFilteringColumn) { (column as MyStuff.MyCustomFilteringColumn).ListDataSource = GetFilterTable(column.DataField); } } } private DataTable GetFilterTable(string Field) { OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + Server.MapPath("~/App_Data/Nwind.mdb")); OleDbDataAdapter adapter = new OleDbDataAdapter(); adapter.SelectCommand = new OleDbCommand("SELECT distinct [" + Field + "] FROM Orders", conn); DataTable myDataTable = new DataTable(); conn.Open(); try { adapter.Fill(myDataTable); } finally { conn.Close(); } return myDataTable; } protected void RadGrid1_ItemCommand(object source, GridCommandEventArgs e) { if (e.CommandName == "ClearFilters") { foreach (GridColumn column in RadGrid1.MasterTableView.Columns) { column.CurrentFilterFunction = GridKnownFunction.NoFilter; column.CurrentFilterValue = String.Empty; } RadGrid1.MasterTableView.FilterExpression = String.Empty; RadGrid1.MasterTableView.Rebind(); } }
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load For Each column As GridBoundColumn In RadGrid1.MasterTableView.Columns If TypeOf column Is MyStuff.MyCustomFilteringColumn Then (CType(column, MyStuff.MyCustomFilteringColumn)).ListDataSource = GetFilterTable(column.DataField) End If Next End Sub Private Function GetFilterTable(ByVal Field As String) As DataTable Dim conn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + Server.MapPath("~/App_Data/Nwind.mdb")) Dim adapter As New OleDbDataAdapter() adapter.SelectCommand = New OleDbCommand("SELECT distinct [" + Field + "] FROM Orders", conn) Dim myDataTable As New DataTable() conn.Open() Try adapter.Fill(myDataTable) Finally conn.Close() End Try Return myDataTable End Function Protected Sub RadGrid1_ItemCommand(ByVal source As Object, ByVal e As GridCommandEventArgs) Handles RadGrid1.ItemCommand If e.CommandName = "ClearFilters" Then For Each column As GridColumn In RadGrid1.MasterTableView.Columns column.CurrentFilterFunction = GridKnownFunction.NoFilter column.CurrentFilterValue = [String].Empty Next RadGrid1.MasterTableView.FilterExpression = [String].Empty RadGrid1.MasterTableView.Rebind() End If End Sub