Search code examples
filteringtelerik-mvc

telerik mvc Create CompositeFilterDescriptor and append it to existing datasource request filter


I am having some issues creating a CompositeFilterDescriptor from scratch.

The scenario: We have date filters on the grid, but are showing date time fields.

When Someone filters to a specific date, we show all records for that day.

when someone filters greater than that day, we edit the filterDescriptor for that filter and add one day to it.

when someone filters to less than or equal to that day, we edit the filterdescriptor for that filter and add one day to it.

Here is the problem: when someone selects "not equal to", the solution would be to create a compositeFilterDescriptor containing two filters. One for less than that day, one for greater than that day.

I may ore may not be doing this part properly. I can not figure out how to add the new compositeFilterDescriptor to the existing dataSourceRequest.

Here is what I have:

static public DataSourceRequest FixDateFilters(DataSourceRequest request, string[] optionalFields = null)
    {
        if (request?.Filters != null)
        {
            List<string> matchingFields = new List<string> { "utc", "time" };
            List<FilterDescriptor> newDescriptors = new List<FilterDescriptor>();

            //if any fields specific to a page have been passed in, append them to the list.
            if (optionalFields != null)
            {
                foreach (string field in optionalFields)
                    matchingFields.Append(field);
            }

            foreach (string matchingField in matchingFields)
            {
                List<FilterDescriptor> descriptors = new List<FilterDescriptor>();
                FilterDescriptor descriptor1 = FindFirstFilterByMember(request.Filters, matchingField, true, null);
                //there could be up to two filters on a matching field.  Get the 2nd one if it exists.
                FilterDescriptor descriptor2 = FindFirstFilterByMember(request.Filters, matchingField, true, descriptor1);

                //turn the matches into a list for iterating
                if (descriptor1 != null)
                    descriptors.Add(descriptor1);
                if (descriptor2 != null)
                    descriptors.Add(descriptor2);
                if (descriptors.Count != 0)
                {
                    foreach (FilterDescriptor descriptor in descriptors)
                    {
                        DateTime? utcDate = (DateTime?)descriptor?.Value;
                        if (utcDate.HasValue)
                        {
                            utcDate = Core.DateHelper.ToUTC(utcDate.Value, HttpContext.Current); //make sure date ranges are one day ranges in local time
                        }

                        if (utcDate != null)
                        {
                            if (descriptor.Operator == FilterOperator.IsLessThanOrEqualTo)
                            {
                                utcDate = ((DateTime)utcDate).AddDays(1);
                                descriptor.Value = utcDate;
                            }
                            else if (descriptor.Operator == FilterOperator.IsGreaterThan)
                            {
                                utcDate = utcDate.Value.AddDays(1);
                                descriptor.Value = utcDate;
                            }
                            else if (descriptor.Operator == FilterOperator.IsEqualTo)
                            {
                                descriptor.Operator = FilterOperator.IsGreaterThanOrEqualTo;
                                newDescriptors.Add(new FilterDescriptor(descriptor.Member, FilterOperator.IsLessThan, utcDate.Value.AddDays(1)));
                            }
                            else if (descriptor.Operator == FilterOperator.IsNotEqualTo)
                            {
                                CompositeFilterDescriptor cfd = new CompositeFilterDescriptor();
                                cfd.LogicalOperator = FilterCompositionLogicalOperator.Or;
                                cfd.FilterDescriptors.Add(new FilterDescriptor(descriptor.Member, FilterOperator.IsLessThan, utcDate.Value;));
                                cfd.FilterDescriptors.Add(new FilterDescriptor(descriptor.Member, FilterOperator.IsGreaterThan, utcDate.Value.AddDays(1)));
                                newDescriptors.Add( cfd);
                            }
                        }
                    }
                }
            }
            //equals matches add a new descriptor so add them after the foreach is done so they don't affect the foreach.
            foreach (FilterDescriptor newDescriptor in newDescriptors)
            {
                if (newDescriptor.Member != "") //a blank descriptor has a emptry string for member
                {
                    request.Filters.Add(newDescriptor);
                }
            }
        }
        return request;
    }

}

    static public FilterDescriptor FindFirstFilterByMember(IEnumerable<IFilterDescriptor> filters, string findMember, bool partialMatch = false, FilterDescriptor previous = null)
    {
        FilterDescriptor ret = null;
        foreach (var filter in filters)
        {
            var descriptor = filter as FilterDescriptor;
            if (descriptor != null 
                && (descriptor.Member == findMember || (partialMatch == true && descriptor.Member.ToLower().Contains(findMember.ToLower()))) 
                && (previous == null || previous != descriptor))
            {
                ret = descriptor;
                break;
            }
            else if (filter is CompositeFilterDescriptor)
            {
                ret = FindFirstFilterByMember(((CompositeFilterDescriptor)filter).FilterDescriptors, findMember, partialMatch, previous);
                if (ret != null)
                    break;
            }
        }
        return ret;
    }

The second function is a recursive one for getting the filters by string.

The problem section is the "isNotEqualTo" comparison. I don't know how to save the composite filter into the existing request. It gives me a casting error.


Solution

  • Ok it turns out all i needed to do was create a new list of CompositeFilterDescriptor type and append that when necessary. The .add function took both. Sigh.

                foreach (CompositeFilterDescriptor newCompositeDescriptor in newCompositeDescriptors)
                {
                    request.Filters.Add(newCompositeDescriptor);
                }