Load-on-demand RadGrid in RadComboBox
The example below shows how to embed a RadGrid control in the template of a RadComboBox. This might be is a swift solution when you want to let users type a string sequence in the combobox input and load data (which matches the given pattern) in a table structure inside the combobox drop-down list. The integration between RadGrid and RadComboBox extends the built-in multi-column combobox feature by feeding the combo with data loaded on demand. When you scroll to navigate through the loaded records, the table headers remain static at the top for a better user experience.
The ASPX file declares a combo box with an ItemTemplate that includes the RadGrid control. The RadComboBox has an OnClientDropDownOpening handler to generate an AJAX request (using a RadAjaxManager control on the same page) that binds the grid when the drop-down list opens. The RadGrid in the template has an OnRowClick event handler for setting the combo box text when the user clicks on a row:
<telerik:RadAjaxManager ID="RadAjaxManager1" runat="server" OnAjaxRequest="RadAjaxManager1_AjaxRequest">
</telerik:RadAjaxManager>
<telerik:RadAjaxLoadingPanel ID="RadAjaxLoadingPanel1" runat="server" Height="75px"
Width="75px" Transparency="15">
<img alt="Loading..." src='<%= RadAjaxLoadingPanel.GetWebResourceUrl(Page, "Telerik.Web.UI.Skins.Default.Ajax.loading.gif") %>'
style="border: 0; margin-top: 100px;" /></telerik:RadAjaxLoadingPanel>
<telerik:RadComboBox RenderMode="Lightweight" ID="RadComboBox1" Width="320px" runat="server" MarkFirstMatch="True"
AllowCustomText="True" OnClientDropDownOpening="HandleOpen" Skin="Telerik" ExpandAnimation-Type="None"
CollapseAnimation-Type="None">
<ItemTemplate>
<telerik:RadGrid RenderMode="Lightweight" ID="RadGrid1" Width="315px" runat="server" Skin="Telerik" OnNeedDataSource="RadGrid1_NeedDataSource">
<MasterTableView NoMasterRecordsText="" AutoGenerateColumns="False" DataKeyNames="OrderID,ProductName,UnitPrice"
Width="278px" ClientDataKeyNames="OrderID,ProductName,UnitPrice" TableLayout="Fixed">
<Columns>
<telerik:GridBoundColumn HeaderText="OrderID" DataField="OrderID" UniqueName="OrderID">
<HeaderStyle Width="75px" />
</telerik:GridBoundColumn>
<telerik:GridBoundColumn HeaderText="ProductName" DataField="ProductName" UniqueName="ProductName">
<HeaderStyle Width="138px" />
</telerik:GridBoundColumn>
<telerik:GridBoundColumn HeaderText="UnitPrice" DataField="UnitPrice" UniqueName="UnitPrice"
DataFormatString="{0:$###,###.##}">
<HeaderStyle Width="65px" />
</telerik:GridBoundColumn>
</Columns>
</MasterTableView>
<ClientSettings>
<ClientEvents OnRowClick="RowClicked"></ClientEvents>
<Scrolling AllowScroll="true" UseStaticHeaders="true" ScrollHeight="300px" />
</ClientSettings>
</telerik:RadGrid>
</ItemTemplate>
<Items>
<telerik:RadComboBoxItem runat="server" Text=" "></telerik:RadComboBoxItem>
</Items>
</telerik:RadComboBox>
The grid's OnRowClick handler ("RowClicked") gets the values from the clicked row and assigns them as the text of the combo box. The combobox's OnClientDropDownOpening handler ("HandleOpen") gets a reference to the AJAX manager and initiates an AJAX request, passing in the string the user entered:
function RowClicked(sender, args) {
var cellValues = args.getDataKeyValue("OrderID") + ", " + args.getDataKeyValue("ProductName") + ", $" + args.getDataKeyValue("UnitPrice");
var combo = $find("<%= RadComboBox1.ClientID %>");
setTimeout(function () { combo.set_text(cellValues); }, 50);
}
function HandleOpen(sender, args) {
var comboText = sender.get_text();
if (comboText.length > 2) {
setTimeout(function () { $find("<%= RadAjaxManager1.ClientID %>").ajaxRequest("LoadFilteredData," + comboText); }, 0);
}
else {
args.set_cancel(true);
}
}
In the code-behind, the Page_Load event handler adds an AJAX setting for the grid to the AJAX manager (now that the templated control is created). The AjaxRequest handler for the RadAjaxManager forces the grid to rebind. The NeedDataSource event handler of the grid binds it based on the string in the combobox:
protected void Page_Load(object sender, EventArgs e)
{
RadGrid grid = RadComboBox1.Items[0].FindControl("RadGrid1") as RadGrid;
RadAjaxManager1.AjaxSettings.AddAjaxSetting(RadAjaxManager1, grid, RadAjaxLoadingPanel1);
}
protected void RadAjaxManager1_AjaxRequest(object sender, AjaxRequestEventArgs e)
{
RadGrid grid = RadComboBox1.Items[0].FindControl("RadGrid1") as RadGrid;
if (e.Argument.IndexOf("LoadFilteredData") != -1)
{
grid.Rebind();
}
}
protected void RadGrid1_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
{
RadGrid grid = source as RadGrid;
if (RadComboBox1.Text != "")
{
String[] vals = RadComboBox1.Text.Split(',');
if (vals.Length > 0)
{
RadComboBox1.Text = vals[0];
}
grid.DataSource = GetDataTable("SELECT [Order Details].OrderID, Products.ProductName, [Order Details].UnitPrice FROM Products, [Order Details] " + "WHERE [Order Details].OrderID LIKE '" + RadComboBox1.Text + "%'" + " AND Products.ProductID=[Order Details].ProductID");
}
else
{
DataTable dt = new DataTable();
dt.Columns.Add("OrderID");
dt.Columns.Add("ProductName");
dt.Columns.Add("UnitPrice");
grid.DataSource = dt;
}
}
public static string connectionString = ConfigurationManager.ConnectionStrings["NorthwindConnectionString"].ConnectionString;
public static DataTable GetDataTable(string query)
{
SqlConnection connection1 = new SqlConnection(connectionString);
SqlDataAdapter adapter1 = new SqlDataAdapter();
adapter1.SelectCommand = new SqlCommand(query, connection1);
DataTable table1 = new DataTable();
connection1.Open();
try
{
adapter1.Fill(table1);
}
finally
{
connection1.Close();
}
return table1;
}