This is a migrated thread and some comments may be shown as answers.

DynamicRadGrid RadCombox Filter MetaForeignKeyColumn

1 Answer 64 Views
Grid
This is a migrated thread and some comments may be shown as answers.
PAUL
Top achievements
Rank 1
PAUL asked on 11 Jan 2012, 03:25 PM

Ok-

Can anyone give me any insight into how the DynamicRadGrid Column Filters work?  Here is the scenario.
I am using DynamicData and the Telerik.Web.UI.DynamicRadGrid. 

I have created a custom class that inherits from ITemplate.   My Custom Template Class builds a RadComboBox using the MetaForeignKeyColumn passed to it.  In the Template Class I have also subscribed to the ComboBox.selectedIndexChanged Event and fire the Filter event passin a new Pair that contains the columnname and value to filter on.

/// <summary>
/// Summary description for ForeignKeyFilterTemplate
/// </summary>
public class DDForeignKeyFilterTemplate : ITemplate
{
    private MetaForeignKeyColumn _column;
    private RadComboBox _ddlb = new RadComboBox();
    private const string NullValueString = "[null]";
    private DSIWebDbDataContext _context;
    private string _filterColumnName = string.Empty;
 
    public DDForeignKeyFilterTemplate(MetaForeignKeyColumn MetaColumn)
    {
        _column = MetaColumn;
        _ddlb.Skin = "WebBlue";
        _ddlb.EnableViewState = true;
        _ddlb.AutoPostBack = true;
        _ddlb.AllowCustomText = false;
        _filterColumnName = _column.ForeignKeyNames[0];
    }
 
    #region ITemplate Members
 
    public void  InstantiateIn(Control container)
    {
        _ddlb.SelectedIndexChanged += new RadComboBoxSelectedIndexChangedEventHandler(_ddlb_SelectedIndexChanged);
     
        if (_ddlb.Items.Count <= 0)
        {
            if (!_column.IsRequired)
                _ddlb.Items.Add(new RadComboBoxItem("[Not Set]"));
          
            PopulateListControl();
             
        }
 
        container.Controls.Add(_ddlb);
    }
 
    void _ddlb_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
    {
        ((GridFilteringItem)(((RadComboBox)sender).Parent.Parent)).FireCommandEvent("Filter", new Pair(e.Text, _column.Name));
    }
 
    private void PopulateListControl()
    {
        _context = (DSIWebDbDataContext)_column.Table.CreateContext();
 
        string PrimaryKeyName = _column.ParentTable.PrimaryKeyColumns[0].Name;
        string DispalyColumnName = _column.ParentTable.DisplayColumn.Name;;
        string ParentTableName = _column.ParentTable.Name;
 
        _ddlb.DataValueField = PrimaryKeyName;
        _ddlb.DataTextField = DispalyColumnName;
 
        switch (ParentTableName)
        {
            case "Bookings":
                loadBookings();
                break;
            case "SiteLocations":
                loadSiteLocations();
                break;
            case "ContainerSizes":
                loadContainerSize();
                break;
            case "Drivers":
                loadDrivers();
                break;
            case "Carriers":
                loadCarriers();
                break;
            case "YardPositions":
                loadYardPositions();
                break;
            case "ContainerTypes":
                loadContainerTypes();
                break;
        }
    }
 
    private void loadBookings()
    {
        var results = _context.Bookings.Select(b => new idname() { id = b.booking_key.ToString(), name = b.Booking_Number });
         
        results.OrderBy(o => o.name);
 
        if (results.Count() > 0)
        {
            foreach (var item in results)
            {
                _ddlb.Items.Add(new RadComboBoxItem(item.name, item.id));
            }
        }
    }
 
    private void loadSiteLocations()
    {
        var results = _context.SiteLocations.Select(b => new idname() { id = b.ref_key.ToString(), name = b.Location });
 
        results.OrderBy(o => o.name);
 
        if (results.Count() > 0)
        {
            foreach (var item in results)
            {
                _ddlb.Items.Add(new RadComboBoxItem(item.name, item.id));
            }
        }
    }

 

 In the DynamicRadGrid Init Method I am creating a new instance of my Template Class and assigning it to the DynamicGridBoundColumn.FilterTemplate. 

DynamicGridBoundColumn gridColumn = new DynamicGridBoundColumn();
 
string fieldName = string.Empty;
string fieldAlias = string.Empty;
 
gridColumn.DataField = column.Name;
gridColumn.ConvertEmptyStringToNull = column.ConvertEmptyStringToNull;
gridColumn.DataFormatString = column.DataFormatString;
gridColumn.UIHint = column.UIHint;
 
gridColumn.HtmlEncode = column.HtmlEncode;
gridColumn.NullDisplayText = column.NullDisplayText;
gridColumn.ApplyFormatInEditMode = column.ApplyFormatInEditMode;
gridColumn.HeaderText = column.DisplayName.Replace("_"," ");
gridColumn.Resizable = true;
 
fieldAlias = column.DisplayName;
fieldAlias = fieldAlias.Replace("_", "");
 
//Set up grouping for ForeignKeyColumns
if (column is MetaForeignKeyColumn)
{
    fieldName = ((MetaForeignKeyColumn)column).ForeignKeyNames[0];
    gridColumn.FilterTemplate = new DDForeignKeyFilterTemplate(((MetaForeignKeyColumn)column));
    gridColumn.FilterListOptions = GridFilterListOptions.VaryByDataTypeAllowCustom;
}
else
{
    fieldName = column.Name;
    fieldAlias = column.DisplayName;
    gridColumn.FilterListOptions = GridFilterListOptions.VaryByDataType;
}
 
// Country [Country], count(Country) Items [Items] Group By Country
gridColumn.GroupByExpression = fieldName + " [" + fieldAlias + "], count(" + fieldName + ") Items [Items] Group By " + fieldName;
 
MasterTableView.Columns.Add(gridColumn);

This works great and I get the RadComboBox boxes with the appropriate ParentTable values as custom filter dropdowns in each column of the Grid.

The issue:
When i select a new value in the dropdowns, i am getting value not found error on the filter event.
I have tried to overload the DynamicGridBoundColumn both the GetCurrentFilterValueFromControl and the SetCurrentFilterValueToControl.

protected override string GetCurrentFilterValueFromControl(TableCell cell)
 {
     if (cell.Controls[0] is RadComboBox)
     {
         string currentValue = ((RadComboBox)cell.Controls[0]).SelectedItem.Text;
 
         this.CurrentFilterFunction = (currentValue != "" && currentValue != "empty ") ? GridKnownFunction.EqualTo : GridKnownFunction.NoFilter;
 
         return currentValue;
     }
     else
         return base.GetCurrentFilterValueFromControl(cell);
 }
 
 protected override void SetCurrentFilterValueToControl(TableCell cell)
 {
     if (cell.Controls[0] is RadComboBox)
     {
         if (!(this.CurrentFilterValue == ""))
         {
             ((RadComboBox)cell.Controls[0]).Items.FindItemByText(this.CurrentFilterValue).Selected = true;
         }
     }
     else
         base.SetCurrentFilterValueToControl(cell);
 }

I have even trapped the event in the Grid_ItemCommand Event setting the FilterExpression on the column and the MasterTableView.

#region Filter Items
if (e.CommandName == RadGrid.FilterCommandName)
{
    Pair filterPair = (Pair)e.CommandArgument;
    GridFilteringItem item = e.Item as GridFilteringItem;
 
    GridColumn filterColumn = item.OwnerTableView.GetColumn(filterPair.Second.ToString());
    filterColumn.CurrentFilterFunction = GridKnownFunction.EqualTo;
    filterColumn.CurrentFilterValue = filterPair.First.ToString();
 
    RadGrid1.MasterTableView.FilterExpression = filterColumn.EvaluateFilterExpression(item);
     
}
#endregion

I'm not sure if there is something i am missing.  The underlying column that i am trying to filter is a DynamicControl and is a ForeignKey so the values of the drid are actually the DisplayName of the parent table.  At one point i was getting a datatype miss-match as the comparer was trying to filter the EntityName (SiteLocation) to a string, which was the value (key) selected in the dropdown from the parrent table.

Any Ideas or help would be appreciated.
Thanks
Paul

1 Answer, 1 is accepted

Sort by
0
PAUL
Top achievements
Rank 1
answered on 11 Jan 2012, 11:47 PM
Solved:
The FilterExpression uses the Entity.ColumnName syntax.

Override the DynameGridBoundColumn.GetFilterDataField.  Originally this call was just returning the DataField name in the FilterExpression.
"(iif(SiteLocation == null, \"\", SiteLocation).ToString() = \"DSI - Expansion\")"

This will throw and error.  Since the SiteLocation is an Enity, actually a ForiegnKey to another table.  We need to override the GetFilterDataField to build the proper filter expression.
protected override string GetFilterDataField()
{
    string _filterDataColumnName=string.Empty;
 
    if (_column is MetaForeignKeyColumn)
    {
        // Foreignkeys which are Entities need to be filtered using the EntityName.ColumnName
        // ex. ColumnName.ParentTable.DisplayColumn.Name
        _filterDataColumnName = Column.Name + "." + ((MetaForeignKeyColumn)Column).ParentTable.DisplayColumn.Name;
    }
    else
    {
        _filterDataColumnName = DataField;
    }
 
    return _filterDataColumnName;
}

Now when the FilterExpression is built for the Entity Column it will produce the following expression.
"(iif(SiteLocation.Location == null, \"\", SiteLocation.Location).ToString() = \"DSI - Expansion\")"

Happy Filtering!
Tags
Grid
Asked by
PAUL
Top achievements
Rank 1
Answers by
PAUL
Top achievements
Rank 1
Share this question
or