Блог Александра Божко
Архивы
Рубрики
Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

Фильтрация

Фильтрация TcxDBGridDBTableView позволяет отображать некоторую выборку из общего набора данных, отображаемого в гриде, заданную по некоторому условию. По умолчанию данная возможность, так же как и возможность сортировки,  включена. Отключить фильтрацию можно с помощью свойства OptionsCustomize.ColumnFiltering:

cxGrid1DBTableView1.OptionsCustomize.ColumnFiltering:= False;

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

  • с помощью выпадающего списка;
  • с помощью панели фильтрации;
  • с помощью диалога построения фильтра;
  • с помощью строки фильтрации.

Если возможность фильтрации включена, то в Run Time мы можем  подвести курсор к правой границе заголовка поля,  на заголовке появится кнопка для разворачивания выпадающего списка, в котором птичками можно отметить значения для фильтрации. Кроме перечня всех имеющихся значений поля, имеется возможность выбрать все записи, пустые или не пустые значения,  а так же задать пользовательский фильтр с помощью специального диалога.

Filter List

Filter List

Filter Dialog

Filter Dialog

Сразу же покажу, как отключить ту или иную дополнительную опцию фильтрации.  В коде, приведенном ниже (обработчик события DataController.Filter.OnGetValueList), отключается пункт “(Custom…)” выпадающего списка и, таким образом, возможность задать пользовательский фильтр становится недоступной.

procedure TForm1.cxGrid1DBTableView1DataControllerFilterGetValueList(
Sender: TcxFilterCriteria; AItemIndex: Integer;
AValueList: TcxDataFilterValueList);
begin
if AValueList.ItemsList.Count>1 then
AValueList.Delete(1);
end;

В список добавить и собственные значения. В официальной  документации есть пример того, как реализовать данный функционал.

После того, как фильтр установлен в нижней части грида (опять же, по умолчанию) появляется панель фильтрации. Данная панель  позволяет не только применить/отменить фильтрацию, но и сохранить историю фильтров, а так, же задать фильтр с помощью диалога построения фильтра.

Еще один способ задать фильтр – строка фильтрации. По умолчанию она выключена. Включить ее можно следующим образом:

cxGrid1DBTableView1.FilterRow.Visible:= True;

Если фильтр задается в строковом поле, то при фильтрации используется оператор LIKE, соответственно, мы можем использовать символ “%” в условии фильтрации.

В зависимости от значения свойства FilterRow.ApplyChanges (fracOnCellExit или fracImmediately) фильтр устанавливается либо при выходе из ячейки в строке фильтрации, либо непосредственно при вводе символов.

Попробуем разобраться, как работать с фильтром  с помощью кода.

За фильтрацию данных отвечает свойство DataController.Filter, которое имеет тип TcxFilterCriteria. TcxFilterCriteria – родительский класс для TcxDataFilterCriteria и TcxDBDataFilterCriteria. Эти классы, соответственно, работают с  не привязанными или привязанными к БД данными.

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

cxGrid1DBTableView1.DataController.Filter.Root.Clear;

Для того, что бы задать собственный фильтр нужно в первую очередь указать логический оператор, в соответствии с которым будут объединяться условия. Для этого присвоим значение свойству BoolOperatorKind, например:

cxGrid1DBTableView1.DataController.Filter.Root.BoolOperatorKind := fboOr;

BoolOperatorKind имеет тип TcxFilterBoolOperatorKind = (fboAnd, fboOr, fboNotAnd, fboNotOr).

После того, как мы задали логический оператор, мы можем добавлять условия фильтрации, используя метод  AddItem:

function AddItem(AItemLink: TObject; AOperatorKind: TcxFilterOperatorKind;
const AValue: Variant; const ADisplayValue: string): TcxFilterCriteriaItem;

В качестве первого параметра зададим столбец  View, по которому производится фильтрация.
Оператор может принимать одно из следующих значений:

TcxFilterOperatorKind = (foEqual,
foNotEqual, foLess, foLessEqual,
foGreater, foGreaterEqual, foLike,
foNotLike, foBetween, foNotBetween,
foInList, foNotInList,    foYesterday, foToday, foTomorrow,
foLast7Days, foLastWeek, foLast14Days, foLastTwoWeeks,
foLast30Days, foLastMonth, foLastYear, foInPast,
foThisWeek, foThisMonth, foThisYear,    foNext7Days,
 foNextWeek, foNext14Days, foNextTwoWeeks, foNext30Days,
foNextMonth, foNextYear, foInFuture);

Через параметр AValue передается значение фильтра. Последний параметр – то значение, которое будет отображаться в панели фильтрации (Filter Panel).

Активировать фильтр можно следующим образом:

cxGrid1DBTableView1.DataController.Filter.Active:=True;

Данный фрагмент кода устанавливает фильтр по полю “Service”. Выбираются значения

cxGrid1DBTableView1.DataController.Filter.Root.Clear;
cxGrid1DBTableView1.DataController.Filter.Root.BoolOperatorKind := fboOr;
cxGrid1DBTableView1.DataController.Filter.Root.AddItem(cxGrid1DBTableView1Service, foEqual, 'Блогосфера', 'Блогосфера' );
cxGrid1DBTableView1.DataController.Filter.Root.AddItem(cxGrid1DBTableView1Service, foLike, 'prog%', 'prog...' );
cxGrid1DBTableView1.DataController.Filter.Active:=True;

Тема фильтрации в DevExpress весьма обширна и, пожалуй, то, что было рассмотрено в данном посте – лишь надводная часть айсберга. В заключение хочу отметить один, как мне кажется принципиальный, момент. Если сравнивать реализацию сортировки и фильтрации, скажем, с тем же GridEh, то можно увидеть одно принципиальное отличие. Процитирую документацию LibEh. DBGridEh не может сортировать или фильтровать данные самостоятельно. Но он может послать команду для сортировки или фильтрации специальному объекту, который сделает это в DataSet‘е. В нашем же случае, обрабатывается внутренний набор данных, фильтрация и сортировка которого никак не влияет на подключенный DataSet. В ряде случаев такой подход  дает неоспоримые преимущества.

Другие статьи серии:

DevExpress. Заметки на полях #0
DevExpress. Заметки на полях #1
DevExpress. Заметки на полях #2
DevExpress. Заметки на полях #3
DevExpress. Заметки на полях #3.5
DevExpress. Заметки на полях #5
DevExpress. Заметки на полях #6
DevExpress. Заметки на полях #7
DevExpress. Заметки на полях #9
DevExpress. Заметки на полях #10
DevExpress. Заметки на полях #11
DevExpress. Заметки на полях #12
DevExpress. Заметки на полях #13


Поделись с другими!
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

7 комментариев: DevExpress. Заметки на полях #8

  • Заметил, что на очень большом количестве данных (десятки тысяч записей), фильтрация средствами TdxGrid работает значительно быстрее фильтрации по стандартному DataSet.

  • > В нашем же случае, обрабатывается внутренний набор данных, фильтрация и сортировка которого никак не влияет на подключенный DataSet.
    Получается, что на большом наборе записей, все записи Dataset-a подключенного к cxGrid будут зафетчены в память?
    Я немного работал с одной очень старой версией cxGrid-a, в самом начале своей карьеры программиста. И насколько я помню, для нормальной работы фильтров и локальной сортировки грид загонял в память все записи, и при больших каталогах с большим числом полей, программа начинала отъедать довольно существенныый кусок памяти. (это было во времена, когда большинство офисных компов имели 128 или 256 мб оперативки). В этом плане фильтрация изменяющая Sql запрос Datasetа выглядела намного более привлекательной.
    Впрочем, к чести Ehlib-a стоит сказать что он поддерживает 2 режима фильтров, локальный и через изменение SQL-запроса. cxGrid 3й версии, вроде имел такую же возможность.

    • Как я понимаю, за все эти вещи в cxGrid отвечает dataController, и там, опять же, как я понимаю, своя индексация и оптимизация. По крайней мере, все это происходит довольно быстро.

      Естественно, что DataSet будет фетчится полностью.

      Хотя ни кто не мешает и в cxGrid сделать фильтрацию по аналогии со вторым режимом EhLib (обновить запрос для dataSet). Ко всему, что “нарисовано” на гриде есть доступ. и обработать там можно все как угодно. Если честно, я не пробовал, но уверен, что извернуться можно.

      • Не только можно, но и нужно для больших
        объемов данных.
        1. Для фильтрации по SQL
        У DataController’a поймать событие
        Filter.OnBeforeChange. В нем можно получить
        текст условий sql запроса сгенерированный фильтром
        и применить его к запросу.
        Для поддержки особенностей SQL рекомендуется
        сделать свой FilterOperatorAdapter и зарегистрировать
        его на нужный класс DataSet:
        cxFilterOperatorAdapters.RegisterAdapter(TSmartQuery, TcxODACFilterOperatorAdapter);

        Тоже самое с сортировкой. У DataController’а поймать
        событие OnSortingChange и собрать строку order by для ЫЙД

  • Может кто подскажет как решить мою проблему – колонка в cxGrid подключена к полю локапному датасета, которое тянет значения из другого датасета по индексу.
    При открытии фильтра получаю список с невообразимой сортировкой – как получить упорядоченный список?

    • cxDBGridDBTableView1Column1.Option.SortByDisplayText:= isbtOn; ?

      Правда, судя по документации это свойство для других целей. но помогает.

Продукты DevArt
Купить онлайн:



Читай русскоязычные Delphi блоги
Каталог блогов Blogdir.ru
Яндекс.Метрика