#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);
}