Вопрос пользователя заключается в том, как отобразить иерархию категорий в Embarcadero Delphi 2010, используя Access-базу данных. В таблице MCategory присутствует колонка parentcategory, которая указывает на родительскую категорию для каждой записи. Пользователь хочет отобразить эту иерархию в виде дерева на DBGrid, не прибегая к сложным рекурсивным методам.
Для решения этой задачи можно использовать следующий подход:
Преобразование всех записей набора данных в TStringList и их сортировка.
Реализация компонента TCategoryItem, который будет содержать информацию о категории, включая родительскую категорию и идентификатор.
Обработка события AfterOpen компонента ADOQuery, где происходит добавление каждого элемента в TStringList.
Создание процедуры OnGetFieldText, которая будет обрабатывать текст родительской категории, формируя иерархию.
Привязка процедуры OnGetFieldText к полю parentcategory в ADOQuery для отображения иерархии в DBGrid.
Вот пример кода, который можно использовать для реализации предложенного подхода:
type
TCategoryItem = class
private
FCategoryTitle: string;
FId, FParentId: Variant;
public
property CategoryTitle: string read FCategoryTitle write FCategoryTitle;
property Id: Variant read FId write FId;
property ParentId: Variant read FParentId write FParentId;
end;
var
RecordList: TStringList;
procedure TForm1.AdoQuery1AfterOpen(DataSet: TDataSet);
var
Item, RootItem: TCategoryItem;
begin
DataSet.First;
DataSet.DisableControls;
try
// Добавление корневого элемента в RecordList, если это необходимо
// RootItem := TCategoryItem.Create;
// RootItem.CategoryTitle := 'ROOT';
// RecordList.AddObject('', RootItem);
while not DataSet.Eof do
begin
Item := TCategoryItem.Create;
Item.CategoryTitle := DataSet['category'];
Item.Id := DataSet['codecategory'];
Item.ParentId := DataSet['parentcategory'];
RecordList.AddObject(VarToStr(Item.Id), Item);
DataSet.Next;
end;
finally
RecordList.Sort; // для использования бинарного поиска
DataSet.EnableControls;
DataSet.First;
end;
end;
procedure TForm1.OnGetFieldText(Sender: TField; var Text: string;
DisplayText: Boolean);
var
Idx: Integer;
ParentValue: Variant;
Item: TCategoryItem;
Texts: TStringList;
begin
ParentValue := Sender.Value;
Texts := TStringList.Create;
try
while RecordList.Find(VarToStr(ParentValue), Idx) do
begin
Item := RecordList.Objects[Idx] as TCategoryItem;
Texts.Insert(0, Item.CategoryTitle);
ParentValue := Item.ParentId;
end;
Texts.Delimiter := '>';
Text := Texts.DelimitedText;
finally
Texts.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ADOQuery1.FieldByName('parentcategory').OnGetText := OnGetFieldText;
ADOQuery1.Refresh;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RecordList := TStringList.Create(True);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
RecordList.Free;
end;
Этот код предполагает, что события OnCreate и OnDestroy формы будут использоваться для создания и освобождения TStringList. Процедура OnGetFieldText используется для модификации отображаемого текста для одного поля, не для вычислений, связанных с набором данных; для таких вычислений следует использовать TDataset.OnCalcFields. Однако, если рассматривать большие объемы данных, предпочтительнее было бы выполнение подобных операций на стороне сервера, в базе данных, а не на клиенте.
Использование TStringList для сортированного доступа может быть быстрее, чем использование TDictionary, так как поиск в TStringList использует бинарный поиск, в то время как TDictionary использует поиск по хешу. Также стоит учесть, что если вы выполняете ограниченный выбор категорий (SELECT...WHERE), вам нужно будет загрузить все категории заранее, так как иначе вы не сможете найти родительские категории, если они не были загружены изначальным запросом.
Вопрос связан с реализацией иерархического отображения категорий в Embarcadero Delphi 2010 с использованием Access-базы данных, где для каждой категории указана родительская категория, и задача состоит в отображении этой иерархии в виде дерева
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.