Filtering RadGridView in Dynamic Columns

1 Answer 204 Views
GridView
Benjamin
Top achievements
Rank 1
Benjamin asked on 09 Nov 2023, 02:27 PM | edited on 09 Nov 2023, 04:49 PM

Hello,

 

we have a RadGridView which we define in a .xaml file. To this grid we add a few dynamic columns via a Behavior. Our Problem now is, that the columns we defined in the .xaml-file can be filtered normaly, but the dynamicaly added columns are missing the filter icon in the column header. We tried adding a new Instance of the FilterControl which shows the filter icon, but the FilterControl does not do anything and is missing the Search Textboxes.

 

Can you guide us advice on what we need to do to get the filter working for those columns?

 

Here is the code of the Behavior we use to add the dynamic columns:

 


public class RadGridViewAddCustomFieldDefinitionColumnsBehavior : RadGridViewAddFieldDefinitionColumnsBehavior<CustomFieldDefinition>
{
    protected override void AddFieldsColumns(
        IEnumerable<CustomFieldDefinition> fieldDefinitions,
        GridViewDataControl radGridView,
        RadGridViewAddFieldDefinitionColumnsBehavior<CustomFieldDefinition> radGridViewAddFieldColumnsBehavior)
    {
        var corporationIDToNameConverter = new CorporationIDToNameConverter();
        var contactIDToNameConverter = new ContactIDToNameConverter();

        foreach (var customFieldDefinition in fieldDefinitions)
        {
            var column = new GridViewDataColumn
                         {
                             Header = customFieldDefinition.PropertyName,
                             UniqueName = customFieldDefinition.PropertyName,
                             DataMemberBinding = new Binding("CustomFields")
                                                 {
                                                     Converter = new ValueConverterChain
                                                                 {
                                                                     optionalDictionaryValueConverter,
                                                                 },
                                                     ConverterParameter = new ValueConverterChainParameters
                                                                          {
                                                                              customFieldDefinition.ID,
                                                                          },
                                                 },
                         };

            switch (customFieldDefinition.FieldType)
            {
                case FieldType.Corporation:
                    SetColumnValueConverter(column, customFieldDefinition, corporationIDToNameConverter);
                    break;
                case FieldType.Contact:
                    SetColumnValueConverter(column, customFieldDefinition, contactIDToNameConverter);
                    break;
            }

            CurrentFieldDefinitionColumns.Add(column);
            radGridView.Columns.Add(column);
        }
    }

    protected override void SetColumnValueConverter(
        GridViewDataColumn column,
        CustomFieldDefinition fieldDefinition,
        IValueConverter valueConverter)
    {
        var converterChain = (ValueConverterChain)column.DataMemberBinding.Converter;
        var valueConverterChainParameters = (ValueConverterChainParameters)column.DataMemberBinding.ConverterParameter;

        converterChain.Add(valueConverter);
        valueConverterChainParameters.Add(fieldDefinition.Values);
    }
}

 

Kind regards

 

Benny

1 Answer, 1 is accepted

Sort by
0
Martin Ivanov
Telerik team
answered on 13 Nov 2023, 12:23 PM

Hello Benjamin,

The filtering and sorting operations in RadGridView works with the direct object bound through the DataMemberBinding. Converters in the binding are not supported. You can use them only for the display value. In other words, the column will try to filter/sort the type of CustomFields property, which I will guess is a dynamic object, a dictionary, or another type of data structure. 

There is a feature request to allow the data operations work when converter is used with the DataMemberBinding: https://feedback.telerik.com/wpf/1354013-add-an-option-to-filter-a-column-on-the-converted-values

In the meantime, for the dynamic columns, you can consider using an approach without converter. For example, you can try using dynamic objects or properties defined directly in the data model, instead of the CustomFields collection. 

Regards,
Martin Ivanov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Benjamin
Top achievements
Rank 1
commented on 16 Nov 2023, 07:27 PM

Hello Martin,

Thanks for your answer. I changed the code as you suggested, I now bind to a dictionary of type <int, object> and set the FilterMemberType manually. This works fine except for one problem I now have: When I open the column filter via the filter symbol the first time, I can't search for anything, because the 2 filter TextBoxes are missing. When I close the filter dialog for this column and open it again, I can filter perfectly fine as intended (see attached screenshot).

Gif showing wrong behavior

Can you give me a hint what I am still doing wrong here? Here is the updated code I am using to setup the columns:

protected override void AddFieldsColumns(
        IEnumerable<CustomFieldDefinition> fieldDefinitions,
        GridViewDataControl radGridView,
        RadGridViewAddFieldDefinitionColumnsBehavior<CustomFieldDefinition> radGridViewAddFieldColumnsBehavior)
    {
        foreach (var customFieldDefinition in fieldDefinitions)
        {
            var column = new GridViewDataColumn
                         {
                             Header = customFieldDefinition.PropertyName,
                             UniqueName = customFieldDefinition.PropertyName,
                             IsFilterable = true,
                             FilteringControl = new FilteringControl(),
                             ShouldGenerateFieldFilterEditors = true,
                             FilterMemberType = GetFilterMemberTypeByFieldType(customFieldDefinition.FieldType),
                             DataMemberBinding = new Binding("CustomFields")
                                                 {
                                                     Path = new PropertyPath($"CustomFields[{customFieldDefinition.ID}]")
                                                 },
                         };

            CurrentFieldDefinitionColumns.Add(column);
            radGridView.Columns.Add(column);
        }
    }

    private Type GetFilterMemberTypeByFieldType(FieldType fieldType)
    {
        switch (fieldType)
        {
            case FieldType.Text:
            case FieldType.File:
            case FieldType.Catalog:
            case FieldType.OrganizationItem:
            case FieldType.Process:
            case FieldType.ProjectsItem:
            case FieldType.Corporation:
            case FieldType.Contact:
            case FieldType.CommodityGroup:
            case FieldType.TermsOfPayment:
                return typeof(string);

            case FieldType.Date:
                return typeof(DateTime);

            case FieldType.CheckBox:
                return typeof(bool);

            case FieldType.Percent:
            case FieldType.Decimal:
                return typeof(decimal);
            default:
                throw new ArgumentOutOfRangeException(nameof(fieldType), fieldType, null);
        }
    }

 

Kind regards

Benny

Benjamin
Top achievements
Rank 1
commented on 17 Nov 2023, 01:33 PM

Small correction: This only works forf string columns. The filter values are shown correctly for example for DateTime columns, but filtering for valid values clears the whole Grid.
Martin Ivanov
Telerik team
commented on 21 Nov 2023, 09:35 AM

Hi Benny. To resolve the issue with the missing field filter TextBox elements, you can provide the column in the constructor of the FilteringControl.

var column = new GridViewDataColumn
 {
	 // other settings here
 };
 column.FilteringControl = new FilteringControl(column);

Benjamin
Top achievements
Rank 1
commented on 21 Nov 2023, 04:26 PM

Hey Martin,

perfect, this resolved the first issue, the textboxes are now initially visible. But I still have the problem, that for example the date-field filter does not work, when filtering for a date that exists in the grid, the grid becomes completely empty. As already said I now bind to a dictionary of type <int, object>.

Any help would be highly appreciated.

Martin Ivanov
Telerik team
commented on 24 Nov 2023, 09:10 AM

I've tested this but couldn't recreate the issue. You can check the attached project and tell me if I am missing anything.
Benjamin
Top achievements
Rank 1
commented on 30 Nov 2023, 02:07 PM

Hey Martin,

your example had the same problem with our data, but this gave me the clue why it was not working. I set FilterMemberType to

typeof
(DateTime)

but correct would be

typeof(DateTime?)

 

One last problem I stumbled over: I can't sort by those fields, what do I need to set to be able to sort those columns?

 

Kind regards

Benny

Martin Ivanov
Telerik team
commented on 04 Dec 2023, 02:12 PM

To enable sorting in this scenario, you can set also the DataType property of the column.

 DataType = filterMemberType

Tags
GridView
Asked by
Benjamin
Top achievements
Rank 1
Answers by
Martin Ivanov
Telerik team
Share this question
or