procedure TMainForm.ButtonlClick(Sender: TObject);
var aField: string;
aFieldlndex: integer;
begin
aField := DBGridl.SelectedField.FieldName;
aFieldlndex := SortFields.IndexOf(aField);
if aFieldlndex <> -1 then begin
SortFields.Delete(aFieldlndex);
DBGridl.SelectedField.DisplayLabel := aField;
ReSort;
end;
end;
Пользователь выделяет поле, которое хочет удалить из сортировки, и нажимает на кнопку "Delete column from Sorting", после чего это поле удаляется из списка SortFields и производится пересортировка записей.
Локальная фильтрация
Аналогично локальной сортировке, которая оперирует только с данными в локальном буфере, мы можем также выбирать записи из уже полученных по какому-либо критерию, скрывая от пользователя "лишние" записи.
Рассмотрим локальную фильтрацию на примере приложения Filtering. Этот пример включен в стандартную поставку FIBPlus. В примере используется база данных FIBPlus_Example.gdb (рис. 2.68).
Эта база данных в виде backup-файла доступна на сайте http://www.fibplus.net/
Рис 2.68. Использование локальной фильтрации TpFIBDataSet
Совершенно очевиден код для подключения к базе данных. Список элементов компонента FieldsC: TComboBox заполняется названиями полей из таблицы BIOLIFE.
FilteringDS.SelectSQL: SELECT * FROM BIOLIFE
procedure TMainForm.btnConnectClickfSender: TObject);
var Index: Integer;
begin
with MainDB do begin
ConnectParams.UserName := edtUserName.Text;
ConnectParams.Password := edtPassword.Text;
DBName := edtDataBase.Text;
try
Open;
FilteredDS.Open;
FieldsC.Items.Clear;
for Index := 0 to pred(FilteredDS.FieldCount) do
FieldsC.Items.Add(FilteredDS.Fields[Index].FieldName);
except
MessageDlgt'Error of connection to a database!', mtError, [mbOk], 0) ;
Close;
end;
end;
end;
Пользователь может выбрать поле из списка FieldsC, указать в поле FilterE: TEdit строку для поиска и после нажатия на кнопку Button I ("Activate Filter"):
procedure TMainForm.ButtonlClick(Sender: T0b3ect);
begin
FilteredDS.Filtered := false;
FilteredDS.Filtered := true;
end;
в DBGrid 1 останутся видны только те записи, которые содержат в заданном поле искомую строку Для этого нам необходимо написать обработчик события OnFilterRecord у FilteringDS:
procedure TMainForm.FilteredDSFilterRecord(DataSet: TDataSet;
var Accept: Boolean); begin
Accept := DOS(FilterE.Text,
FilteredDS.FieldByName(FieldsC.Text).AsString) <> 0
end;
После включения FilteredDS.Filtered := true OnFilterRecord вызывается для каждой записи в локальном буфере. Если мы хотим, чтобы конкретная запись оставалась видимой, мы должны задать для нее параметр Accept равным True. Из примера кода видно, что мы оставляем видными только те записи, которые содержат в искомом поле (FieldsC.Text) заданную строку (FilterE.Text). Если мы, например, выберем поле COMMON_NAME и укажем строку для поиска "А", то в результате получим только две видимые записи (рис. 2.69).
Рис 2.69. Пример двух "отфильтрованных" записей
Поскольку наше условие для фильтра сформулировано таким образом, что мы выбираем записи по точному включению искомой подстроки - в нашем случае это только те записи, которые содержат большую букву "А". Мы можем немного усложнить условие поиска. Положим на форму CaseC: TcheckBox (см. рис. 2.69, "Case sensitive") и перепишем обработчик OnFilterRecord следующим образом:
procedure TMainForm.FilteredDSFilterRecord(DataSet: TDataSet;
var Accept: Boolean);
begin
if CaseC.Checked then
Accept := pos(FilterE.Text,
FilteredDS.FieldByName(FieldsC.Text).AsString) <> 0
else
Accept := pos(AnsiUpperCase(FilterE.Text),
AnsiUpperCase(FilteredDS.FieldByName(FieldsC.Text).AsString))
<> 0;
end;
Очевидно, что теперь если пользователь отключит "флажок" "Case sensitive", то фильтр по строке "А" будет содержать гораздо большее количество записей - все записи, которые содержат хотя бы одну букву "А", неважно маленькую или большую (рис. 2.70).
Рис 2.70. Записи, содержащие букву "А"
Очевидно, что использование локальной фильтрации дает разработчику в руки очень гибкое средство построения условий, поскольку этот механизм не столько ограничен, как SQL в условиях WHERE. На основе локальной фильтрации, например, очень легко создается механизм быстрого поиска записи по первым буквам, которые пользователь набирает в поле редактирования.
Обработка событий InterBase при помощи FIBPIus
InterBase дает разработчику некоторый механизм для синхронизации приложений в многопользовательской среде Event Alerts. Суть данного механизма состоит в том. что вы можете вызывать пользовательские события из триггеров или хранимых процедур при помощи функции POST_EVENT:
CREATE PROCEDURE SHOW_EVENT(
EVENT_ID INTEGER)
AS
BEGIN
IF (:EVENT_ID = 1) THEN POST_EVENT 'TEST_EVENT1';
IF (.EVENT_ID = 2) THEN POST_EVENT 'TEST_EVENT2';
IF (.EVENT_ID = 3) THEN POST_EVENT 'TEST_EVENT3';
EXIT;
END
Создадим приложение (рис 2.71), которое будет вызывать данную процедуру и получать соответствующие события Если вы впоследствии попробуете запустить это приложение на двух компьютерах, то оба приложения будут получать сообщения вне зависимости оттого, кто их инициировал
Рис 2.71. Использование InterBase events, при помощи компонента TSIBfibEventAlerter
Для вызова хранимой процедуры мы будем использовать специальный компонент pFIBStoiedPioc TpFIBStoredPioc, задав свойство StoiedProcName (рис 2.72)
Рис 2.72. Вызов хранимой процедуры при помощи компонента TpFIBStoredPioc
Компонент TpFIBStoredProc является прямым потомком TpFIBQuery и сам формирует свойство SQL в виде ' EXECUTE PROCEDURE ...' Название процедуры задается свойством StoiedProcName
Компонент SffifibEventAlerterclass="underline" TSffifibEventAlerterlпредназначен для получения приложением событий InterBase Компонент ссылается на конкретное подключение к базе данных, т.е. на компонент типа TpFIBDatabase (рис 2.73)
Рис 2.73. Свойства SIBfibEventAlerterl
Установим свойство AutoRegister в False, чтобы собственноручно зарегистрировать нужные нам события, а в свойстве Events перечислим те события, которые нас интересуют (рис. 2.74).
Рис 2.74. Список зарегистрированных событий
Чтобы компонент SIBfibEventAlerterl "получал" события, мы должны зарегистрировать их после подключения к базе данных. Для этого напишем обработчик события OnConnect у компонента pFIBDatabaseclass="underline"
procedure TForml.pFIBDatabaselConnect(Sender: TObject);
begin
if not SIBfibEventAlerterl.Registered then
SIBfibEventAlerterl.RegisterEvents;
end;
Соответственно перед закрытием подключения желательно "отключить" SIBfibEventAlerterl. Для этого создадим обработчик события BeforeDisconnect компонента pFIBDatabaseclass="underline"
procedure TForml.pFIBDatabaselBeforeDisconnect(Sender: