telerik mvc создает CompositeFilterDescriptor и добавляет его к существующему фильтру запроса источника данных

#filtering #telerik-mvc

#фильтрация #telerik-mvc

Вопрос:

У меня возникли некоторые проблемы с созданием CompositeFilterDescriptor с нуля.

Сценарий: у нас есть фильтры даты в сетке, но отображаются поля даты и времени.

Когда кто-то фильтрует по определенной дате, мы показываем все записи за этот день.

когда кто-то фильтрует больше, чем этот день, мы редактируем filterDescriptor для этого фильтра и добавляем к нему один день.

когда кто-то фильтрует меньше или равно этому дню, мы редактируем filterdescriptor для этого фильтра и добавляем к нему один день.

Вот проблема: когда кто-то выбирает «не равно», решением было бы создать compositeFilterDescriptor, содержащий два фильтра. Один для меньшего количества дней, один для большего количества дней.

Возможно, я неправильно выполняю эту часть. Я не могу понять, как добавить новый compositeFilterDescriptor в существующий dataSourceRequest.

Вот что у меня есть:

 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 
                amp;amp; (descriptor.Member == findMember || (partialMatch == true amp;amp; descriptor.Member.ToLower().Contains(findMember.ToLower()))) 
                amp;amp; (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;
    }
 

Вторая функция является рекурсивной для получения фильтров по строке.

Проблемный раздел — это сравнение «isNotEqualTo». Я не знаю, как сохранить составной фильтр в существующий запрос. Это выдает ошибку приведения.

Ответ №1:

Хорошо, оказывается, все, что мне нужно было сделать, это создать новый список типа CompositeFilterDescriptor и добавить его при необходимости. Функция .add использовала оба. Вздох.

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