I needed
to create a Google Suggest style
search interface for an ASP.NET
page.
Our site
recently obtained licenses to the Telerik control suite, and the powerful RadGrid control looked like it was just
what I needed. I found this
example on the Telerik site.
Key to
this setup is having a textbox for
the user to input filter criteria, which is then from the user's perspective transformed into a RadComboBox object to house matching
results; then once the user selects an item from the dropdown, the RadGrid is bound and displays any matching
results.
I
encountered a problem because our site uses a centralized class library for CRUD
outside of this particular page’s code class, meaning I could not access my
application’s data context from within the GridBoundColumn class definition. The
Telerik example (specifically in the MyCustomFilteringColumnCS.cs
file) performs its own queries as needed using a SqlDataAdapter with a ConnectionString
obtained from the application configuration. A simple SELECT statement is executed which returns matching results.
When I
tried to reference my centralized data class from within the GridBoundColumn class definition, I got
the following error:
Cannot
access non-static property … in static context.
Below is
the problem code, revealing that the property CurrentUser is inaccessible to the class.
protected void
list_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs e)
{
// Cannot
access non-static property 'CurrentUser' in static context.
using (MyCRUD mc = new MyCRUD(CurrentUser) )
{
((RadComboBox)o).DataTextField
= DataField;
((RadComboBox)o).DataValueField
= DataField;
((RadComboBox)o).DataSource
= mc.GetMatchingAddresses(e.Text);
((RadComboBox)o).DataBind();
}
}
My GridBoundColumn class does not exist
until my application instantiates it with its parent RadGrid object, so I cannot directly
assign a property to it. However, I stumbled upon this post which made me
realize I could, in the GridBoundColumn class definition, make several changes.
- Define a constructor for the class which
takes an existing instance of the MyCRUD
class as input.
- Create a public property in the class definition
which can be assigned the MyCRUD
object.
- Create a private field in the class
definition to contain the instance of the MyCRUD object to be utilized by the GridBoundColumn class.
Below is
the modified class, with additions (*) indicated below.
public class rgcFilterColumn : GridBoundColumn
{
// * I added a constructor with an input parameter of the type
// * corresponding to my app’s CRUD object.
public
rgcFilterColumn(MyCRUD mycrud)
{
TheDataContext = mycrud;
}
// * This field provides an
instance of the rgcFilterColumn class
// * with the corresponding value set for the data
context object.
private
readonly MyCRUD
TheDataContext;
// * This property enables
the process which instantiates this
// * class to assign the MyCRUD object to
TheDataContext.
public
MyCRUD thedatacontext
{
get
{ return TheDataContext; }
}
//
RadGrid will call 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);
RadComboBox
combo = new RadComboBox
{
ID = ("RadComboBox1" + UniqueName),
ShowToggleImage = false,
Skin = "Office2007",
EnableLoadOnDemand = true,
AutoPostBack = true,
MarkFirstMatch = true,
Height = Unit.Pixel(100)
};
combo.ItemsRequested +=
list_ItemsRequested;
combo.SelectedIndexChanged +=
list_SelectedIndexChanged;
cell.Controls.AddAt(0, combo);
cell.Controls.RemoveAt(1);
}
// RadGrid
will call this method when the value should
// be set to the filtering input control(s)
protected
override void
SetCurrentFilterValueToControl(TableCell
cell)
{
base.SetCurrentFilterValueToControl(cell);
RadComboBox
combo = (RadComboBox)cell.Controls[0];
if
((CurrentFilterValue != string.Empty))
{
combo.Text =
CurrentFilterValue;
}
}
// RadGrid
will call this method when the filtering value
// should be extracted from the filtering input
control(s)
protected
override string
GetCurrentFilterValueFromControl(TableCell
cell)
{
RadComboBox
combo = (RadComboBox)cell.Controls[0];
return
combo.Text;
}
protected
void list_ItemsRequested(object o, RadComboBoxItemsRequestedEventArgs
e)
{
// * Below we use the value of field
TheDataContext to execute
// * a method accesible via the MyCRUD data context for the
application.
using (MyCRUD mc = TheDataContext)
{
((RadComboBox)o).DataTextField
= DataField;
((RadComboBox)o).DataValueField
= DataField;
((RadComboBox)o).DataSource
= mc.GetMatchingAddresses(e.Text);
((RadComboBox)o).DataBind();
}
}
private
void list_SelectedIndexChanged(object o, RadComboBoxSelectedIndexChangedEventArgs
e)
{
GridFilteringItem
filterItem = (GridFilteringItem)((RadComboBox)o).NamingContainer;
if
((UniqueName == "Index"))
{
//
this is filtering for integer column type
filterItem.FireCommandEvent("Filter",
new Pair("EqualTo", UniqueName));
}
//
filtering for string column type
filterItem.FireCommandEvent("Filter", new
Pair("Contains",
UniqueName));
}
}
Now an instance of the GridBoundColumn class can happily utilize my application's central CRUD class for all its data retrieval operations.