Delphi 3. Библиотека программиста

Перемещение по иерархии


Для перемещения вверх и вниз по иерархии потребуются две дополнитель ные функции. В рассматриваемом примере пользователь перемещается вниз, когда он делает двойной щелчок на подчиненной записи (справа). При этом фильтр левой таблицы изменяется, и в нее включаются строки из правой таблицы. Затем новый фильтр меняет содержимое правой таблицы— теперь в ней отображаются «дети» выбранной записи. Все это довольно трудно объяснить на словах, поэтому в листинге 13.3 приведен исходный текст обработ чика OnDoubleClick, поясняющий сказанное. Внимательно просмотрите его и убедитесь, что вы поняли принцип его работы.

Листинг 13.3. Обработчик OnDoubleClick для перемещения по иерархии

procedure TForm2.DBGrid2DblClick(Sender : TObject); var NewRangeID, SelectedEmployeeID : String; begin { Выводим информацию о текущей записи } if Table1.FieldByName('Boss_ID').AsString = '' then Label1.Caption := Table2.FieldByName ('Boss_ID').AsString else Label1.Caption := Label1.Caption + ':' + Table2.FieldByName ('Boss_ID').AsString; { Предполагается, что свойство Table1.IndexFieldNames все еще равно 'Boss_ID;Emp_ID' } SelectedEmployeeID := Table2.FieldByName ('Emp_ID').AsString; NewRangeID := Table2.FieldByName ('Boss_ID').AsString; Table1.SetRange([NewRangeID],[NewRangeID]); Table1.FindKey([NewRangeID, SelectedEmployeeID]); end; procedure TForm2.UpOneLevelButtonClick(Sender : TObject); var PrevPos : Integer; NewRangeID : String; begin { Записи фильтруются по Boss_ID выбранного работника. } NewRangeID := Table1.FieldByName ('Boss_ID').AsString; Table1.CancelRange; Table1.IndexFieldNames := 'Emp_ID'; Table1.FindKey([NewRangeID]); NewRangeID := Table1.FieldByName ('Boss_ID').AsString; Table1.IndexFieldNames := 'Boss_ID'; { Восстанавливаем синхронизацию Table2. } Table1.SetRange([NewRangeID],[NewRangeID]); if Table1.FieldByName('Boss_ID').AsString = '' then Label1.Caption := '<Top level>'; else begin PrevPos := 0; while Pos(':', Copy(Label1.Caption, PrevPos + 1, 999))<>0 do PrevPos := Pos(':',Copy(Label1.Caption, PrevPos +1, 999)) + PrevPos; Label1.Caption := Copy(Label1.Caption, 1, (PrevPos - 1)); end; end;

Когда пользователь нажимает кнопку Up One Level, записи левой таблицы фильтруются по значению Boss_ID текущего фильтра. Хотя этот способ и допускает бесконечную рекурсию, вы все равно не сможете легко получить список всех подчиненных текущего начальника вместе с их подчиненными и так далее, вниз по иерархии. Кроме того, вам также не удастся получить всю цепочку вышестоящих начальников. Для этого придется перемещаться по ссылкам в нужном направлении, причем заранее неизвестно, через сколько уровней иерархии потребуется пройти.

Но и такие иерархии приносят пользу — они позволяют выбрать объект любого уровня и при этом снабжают приложение адекватными данными. Например, вы можете последовательно разделять географический регион на более мелкие области, но приложение всегда сможет узнать, к какому региону относятся эти области (кто является родителем самого верхнего уровня).

Кроме того, общие категории можно разделить на отдельные специали зации, но так, чтобы выбор общей категории приводил к включению всех специализаций. Например, при выборе категории «художники» в нее будут автоматически включены художники-портретисты, художники-баталисты, художники-маринисты и т. д. В этом случае для получения списка объектов общей категории вам не придется составлять отдельные списки для членов каждой специализации.



Содержание раздела