I'm building up a grid by dynamically adding Template Columns. The reason I'm using "GridTemplateColumn" is due to the structure of the datasource. The bound object must be used to determine the cell value during data binding. I set the Template Column to a implementation of ITemplate, this class contains the databinding event which determines the cell value.
An example would be the "MyTemplate" class in this example:
http://www.telerik.com/help/aspnet-ajax/grid-programmatic-creation.html
Since I'm setting up all my columns this way, I'm wondering if I will have issues with filtering. I tried setting the "GridTempalteColumn" data type to "DateTime", hoping to get the calendar picker, but it only filtered the filter options. Is it possible to setup my template column with "DateTime" filtering which contains the calendar picker?
I also have a scenario where we would like to have a multi-select dropdown as a filter control. Do you know if this is possible? I've seen examples that use a regular dropdown list, but I haven't noticed anything that allows multiple selections.
Thanks!
10 Answers, 1 is accepted

Take a look into the following documentation for DateTime filtering.
Filtering for DateTime Bound Column with DataFormatString Different from mm/dd/yyyy
This Code Library explains how to use Multi-Selection RadComboBox for filtering grid
Thanks,
Princy.

Do you see any problems with using GridTemplateColumn for all of my columns? I think this is the only option since I must determine the cell value during runtime. Agree? However, I could build up a data table during runtime that I could then bind to the grid, but I'm not sure this would be a better approach.

The example is exactly what I need to implement, however, it needs to be generated dynamically.
I already set the ItemTemplate to a class that inherits ITemplate. Should I create a new class and perform the same approach for "FilterTemplate"? See my examples below:
GridTemplateColumn column = new GridTemplateColumn();
column.UniqueName = e.ColumnUniqueName;
column.ItemTemplate = new ColumnTemplateForLabel(column);
column.FilterTemplate = new FilterTemplateForMultiSelectCombo(e.ColumnUniqueName);
Below is the "FilterTemplate" I'm attempting to setup:
public class FilterTemplateForMultiSelectCombo : ITemplate
{
protected RadScriptBlock script;
protected RadComboBox comboBox;
protected string column = string.Empty;
public FilterTemplateForMultiSelectCombo(string column)
{
this.column = column;
}
public void InstantiateIn(Control container)
{
comboBox = new RadComboBox();
comboBox.ID = string.Format("cmb_{0}", this.column);
comboBox.AutoPostBack = true;
comboBox.DataBinding += new EventHandler(comboBox_DataBinding);
comboBox.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(comboBox_SelectedIndexChanged);
// comboBox.ItemTemplate = Checkbox control added to item template here...
//comboBox.EnableEmbeddedSkins = false;
//comboBox.Skin = "CustomSkin1";
script = new RadScriptBlock();
script.ID = "script_" + column;
string scriptContent = "";
(script.Controls[0] as LiteralControl).Text = scriptContent;
container.Controls.Add(comboBox);
container.Controls.Add(script);
}
// Load Control (Set Datasource)
void comboBox_DataBinding(object sender, EventArgs e)
{
RadComboBox combo = (RadComboBox)sender;
combo.Items.Add(new RadComboBoxItem(string.Empty, string.Empty));
combo.Items.Add(new RadComboBoxItem("Option 1", "Value1"));
combo.Items.Add(new RadComboBoxItem("Option 2", "Value2"));
combo.Items.Add(new RadComboBoxItem("Option 3", "Value3"));
}
void comboBox_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
((GridFilteringItem)(((RadComboBox)sender).Parent.Parent)).FireCommandEvent("Filter", new Pair());
}
}
Below is the "ItemTemplate" I use for my GridTemplateColumns:
public class ColumnTemplateForLabel : ITemplate
{
protected Label lblLabel;
RenderableTabColumn Column;
private Requirement cellParent = null;
private ControlValueUtil<
RenderableTabColumn
, RenderableCellValue> controlValueUtil = new ControlValueUtil<
RenderableTabColumn
, RenderableCellValue>();
public ColumnTemplateForLabel(RenderableTabColumn column)
{
this.Column = column;
}
public void InstantiateIn(Control container)
{
lblLabel = new Label();
lblLabel.ID = Column.Code;
lblLabel.DataBinding += new EventHandler(lblLabel_DataBinding);
container.Controls.Add(lblLabel);
}
void lblLabel_DataBinding(object sender, EventArgs e)
{
Label lbl = (Label)sender;
GridDataItem container = (GridDataItem)lbl.NamingContainer;
cellParent = (Requirement)container.DataItem;
Or would it be better to override my GridColumnTemplate as demonstrated in the following link:
http://www.telerik.com/community/forums/aspnet-ajax/grid/how-to-add-gridboundcolum-with-custom-filtertemplate-all-programmatically.aspx
Thanks!!!
It depends on how exactly you want to perform the filtering. Note that by default the built-in filtering functionality works only for one filter value. So if you need to filter by multiple selected values from the combobox you will need to use an approach similar to the code library that Princy referenced - fire a command (or an ajax request) from the client and handle it on the server where you need to construct the proper filter query and perform the filtering. This way you will override the default filtering functionality of the column. Building a custom filter template as in the code that you have pasted is appropriate in this case.
Inheriting from GridTemplateColumn can be used when you perform filtering by a single value - the methods that are overridden in this case add controls to the filter template and take care to preserve the entered filter value after a postback - e.g. if you have selected a certain item from the combobox and perform filtering the override of GetCurrentFilterValueFromControl will return the proper selected filter value so that is again set to the combobox after postback. This method however returns a single string value so in the case of filtering by multiple values this will not work correctly. That's why you need to manually perform the preserving and resetting of the filter values to the controls in the filter template after a postback has occurred. Otherwise the combo will lose its selected values when you recreate the filter template on postback.
Marin
the Telerik team

You are correct, I need to filter by multiple selections and preserve each selection. I'm currently having trouble setting up the FilterTemplate like the example Princy provided since my Column is created dynamically. I currently have a class setup for both the ItemTemplate and FilterTemplate of my GridTemplateColumn.
Do you have any suggestions for setting this up dynamically? Princy's example is static, mine is setup dynamic using ITemplate.
Below you can see I have my FilterTemplate which also contains another "ItemTemplate" required for the checkbox - "Nested". I'm not sure how to plug in the "onCheckBoxClick" event due to the nesting. I currently have this javascript function on my calling page, but I'm not sure how to pass the values for "Combo" (Since your example uses Container)
GridColumnTemplate <FilterTemplate>
public class FilterTemplateForMultiSelectCombo : ITemplate
{
protected RadScriptBlock script;
protected RadComboBox comboBox;
protected ListValueCollection listOptions;
RenderableTabColumn Column;
public FilterTemplateForMultiSelectCombo(RenderableTabColumn column)
{
this.Column = column;
}
public void InstantiateIn(Control container)
{
comboBox = new RadComboBox();
comboBox.ID = string.Format("cmb_{0}", Column.Code);
comboBox.AutoPostBack = false; // Will be changed to false
comboBox.DataBinding += new EventHandler(comboBox_DataBinding);
comboBox.ItemTemplate = new ColumnTemplateForMultiSelectCombo(Column.Code, comboBox.ID);
container.Controls.Add(comboBox);
}
void comboBox_DataBinding(object sender, EventArgs e)
{
RadComboBox combo = (RadComboBox)sender;
combo.Items.Add(new RadComboBoxItem(string.Empty, string.Empty));
foreach (FilteredListValue item in Column.GetChildren<
FilteredListValue
>().Where(p => p.IsActive).OrderBy(p => p.ValueOrder))
{
combo.Items.Add(new RadComboBoxItem(item.Value, item.Uid));
}
//ListValue defaultOption = listOptions.GetChildren<
ListValue
>().FirstOrDefault(p => p.IsDefault);
//if (defaultOption != null)
//{
// // Check the checkbox for the default list item
// combo.SelectedItem.Value = defaultOption.Value; // Change this...
//}
}
}
ComboBox <TemplateColumn>
public class ColumnTemplateForMultiSelectCombo : ITemplate
{
protected Label lblLabel;
protected CheckBox chkBox;
string Column = string.Empty;
string ComboBox = string.Empty;
public ColumnTemplateForMultiSelectCombo(string column, string comboId)
{
this.Column = column;
this.ComboBox = comboId;
}
public void InstantiateIn(Control container)
{
chkBox = new CheckBox();
chkBox.ID = string.Format("msChk_{0}", Column);
chkBox.Attributes.Add("onclick", "onCheckBoxClick(this, '" + comboBox + "');");
container.Controls.Add(chkBox);
}
}
Test Script to check if the Checkbox selection is working (This throws an error because combo is null)
function onCheckBoxClick(chk, combo) {
alert('Test');
var text = "", values = "";
var combo = $find(combo);
var items = combo.get_items();
for (var i = 0; i < items.get_count(); i++) {
var item = items.getItem(i);
alert('Check Item: ' + item.get_text());
}
}
Thanks for your help!

I got the dropdown setup. It's loading all checkboxes as it should and the "CheckBox" onclick event is firing as expected. The problem is when the ajax request is triggered, it displays an error. Please let me know if you have any suggestions.
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '
<!DOCTYPE html PUB'.
Thanks!

If I comment out the line below which sets the FilterTemplate, the error doesnt occur. In my code below you can see i'm dynamically creating the column and attempting to set the ItemTemplate and Filtertemplate using a class that inherits from ITemplate. Any ideas on why I would be recieving this error message when an ajax request is made (all ajax requests on the page)?
myColumn.FilterTemplate = new FilterTemplateForMultiSelectCombo("combo");
Error:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed. Common causes for this error are when the response is modified by calls to Response.Write(), response filters, HttpModules, or server trace is enabled.
Details: Error parsing near '
<!DOCTYPE html PUB'
Creating the column dynamically - setting both TemplateColumn & FilterColumn
GridTemplateColumn myColumn = new GridTemplateColumn();
myColumn.UniqueName = "Workflow";
myColumn.HeaderText = "<
nobr
>Workflow</
nobr
>";
myColumn.AllowFiltering = true;
myColumn.FilterTemplate = new FilterTemplateForMultiSelectCombo("combo");
myColumn.ItemTemplate = new ColumnTemplateForDetail("lblWorkflow");
this.grdSummary.MasterTableView.Columns.Add(myColumn);
Class used to add combo box to FilterTemplate (the checkbox has been removed while attempting to debug this error). This is a very simple version
public class FilterTemplateForMultiSelectCombo : ITemplate
{
protected RadComboBox comboBox;
string Column;
public FilterTemplateForMultiSelectCombo(string column)
{
this.Column = column;
}
public void InstantiateIn(Control container)
{
comboBox = new RadComboBox();
comboBox.ID = string.Format("fil_{0}", Column);
comboBox.AutoPostBack = false;
container.Controls.Add(comboBox);
}
This is a general error indicating that there is something wrong with the ajax request that is sent to the server. The code for the filter template looks okay. Can you also post any code related to the ajaxifying of the controls. Do you use RadAjaxManager and how do you add the ajax settings. Also how exactly do you trigger the ajax request in the case of the error. Also you can try to replace the RadComboBox with a standard asp.net DropDown control to see if this prevents the error.
If the problem persists I will appreciate if you can send a sample page that replicates the issue so we can investigate it on our side.
Marin
the Telerik team

This means it must be related to the script generated by the Combo Box. Any suggestions on how to fix this??
FilterTemplateForMultiSelectCombo with RadComboBox:
public void InstantiateIn(Control container)
{
comboBox = new RadComboBox();
comboBox.ID = "cmb" + Column.Code;
container.Controls.Add(comboBox);
}
FilterTemplateForMultiSelectCombo with LABEL:
public void InstantiateIn(Control container)
{
lblLabel = new Label();
lblLabel.ID = "lblTest" + Column.Code;
container.Controls.Add(lblLabel);
}
** You can see in my previous post, I'm setting my grid column FilterTemplate to this class which implements ITemplate. My code is very complex and would be very difficult to break into an example. Since I've narrowed it down to the RadCombobox I'm hoping this is sufficient, please let me know what you think. Although, if you must have an example, I'll work on getting it to you.
Thanks!!
I tried to reproduce the error using the filter template with RadComboBox and adding dynamically a template column to the grid but to no avail. The error is most likely related to the way you add ajax settings to the grid and the controls inside it. The problem is not in the filter templates themselves but in the fact that you have script controls (e.g. RadComboBox) in this template. For some reason after an ajax request the control is not recreated properly. Which might be caused by wrong ajax settings. That's why I will appreciate if you can specify how exactly you add the ajax settings in the grid and possibly provide a full runnable page that replicates the problem so that we can investigate it on our side.
Thank you for your cooperation.
Marin
the Telerik team