![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TreeView [D7]
ДяволСД © (2006-10-18 08:18:00)Мне из базы нужно заполнить TreeView сделающим образом
Корень
Категория 1
Подкатегория 1
подподкатегория 1
Подкатегория 2
Категория 2
И т.д....
Желательно ещё у ентих пунктов как-то хранить ID категории из базы. Данные в базе следующего вида: catid (ID категории), parentid (ID родителя категории 0 - родитель корень), name (Имя категории), ...
Как сие оптимально реализовать? Пасибо заранее за ответ!
Loginov Dmitry (2006-10-19 07:50:00) [1]Может здесь че-нить полезного найдешь:
procedure TCardsFrame.BuildTreeByDBData;
var
MainNode, TempNode, SelectNode: TTreeNode;
I: Integer;
NodeList: TList;
CardData: PCardData;
AKey: Integer;
begin
if CardioDM.dstCards.FieldByName('CRD_ID').IsNull then
AKey := -1
else
AKey := CardioDM.dstCards.FieldByName('CRD_ID').AsInteger;
DBTreeView.Items.BeginUpdate;
ClearData;
DBTreeView.Items.Clear;
// Создаем корень дерева
MainNode := DBTreeView.Items.AddChild(nil, 'Все картотеки');
with MainNode do
begin
ImageIndex := 1;
SelectedIndex := 1;
end;
SelectNode := MainNode;
NodeList := TList.Create;
try
with CardioDM.dstCards do
begin
First;
while not Eof do
begin
TempNode := DBTreeView.Items.AddChild(MainNode, FieldByName('CRD_NAME').AsString);
with TempNode do
begin
New(CardData);
FillChar(CardData^, SizeOf(TCardData), 0);
CardData^.cdKey := FieldByName('CRD_ID').AsInteger;
if CardData^.cdKey = AKey then SelectNode := TempNode;
if not FieldByName('CRD_OWNERID').IsNull then
CardData^.cdOwnerKey := FieldByName('CRD_OWNERID').AsInteger;
if not FieldByName('CRD_DATE').IsNull then
CardData^.cdDate := FieldByName('CRD_DATE').AsDateTime;
Data := CardData;
end;
// Добавляем новый итем в список
NodeList.Add(TempNode);
Next;
end;
// Упорядочиваем итемы в соответствии в CRD_OWNERID
for I := 0 to NodeList.Count - 1 do
TTreeNode(NodeList[I]).MoveTo(FindParentNode(TTreeNode(NodeList[I])), naAddChild);
end;
finally
NodeList.Free;
DBTreeView.Items.EndUpdate;
end;
// Выделяем необходымый итем
DBTreeView.Selected := SelectNode;
end;
markers (2006-10-18 23:53:00) [2]to Сергей М.
Мдя, столкнулся с такой проблемой, почему-то в не находил родителя...
Начал переделывать на рекурсию... Толи чё-то не так делаю (Давно в Дельфях не работал и долго в PHP) толи чё.... Вообщем вот код
function catfill(parentid:string='0'; pnod : TTreeNode = nil):Boolean;
var nod: TTreeNode;
begin
ResRow:=DB.exec('SELECT * FROM mag_categories WHERE parentid = '+onequote+
parentid+onequote+' AND cattype <> '+onequote+'Deleted'+onequote+' ORDER ' +
'BY `name` ASC');
while not ResRow.eof do
begin
nod := Tree.Items.AddChild(pnod,VarToStr(ResRow[4]));
nod.Data := Pointer(StrToInt(VarToStr(ResRow[0])));
catfill(ResRow[0],nod);
ResRow.next;
end;
end;
Как я понял вызов построения детей происходит и от туда уже не возвращается..... :( если закоментировать catfill(ResRow[0],nod); то построится дерево подчинёных корню (как и должно быть). Подскажите плиз!
Сергей М. (2006-10-18 12:03:00) [3]
> Можно сделать что если узел не найден то делать корнем
Хм ... В базе элемент дерева числится как дочерний, а в TreeView он вдруг ни с того ни с сего выглядит корневым ? Ну и разве это правильно ? Подумай ... Дело даже не в том как это визуально выглядит - такая ситуация чревата серьезными ошибками при дальнейшей модификации базы ..
Amoeba (2006-10-18 11:44:00) [4]http://www.delphikingdom.com/asp/viewitem.asp?catalogid=783
ДьяволСД (2006-10-18 11:27:00) [5]Можно сделать что если узел не найден то делать корнем.
Сергей М. (2006-10-18 11:08:00) [6]Боюсь что твой алгоритм когда-нибудь затрещит по швам.
Вот смотри :
else if StrToInt(VarToStr(ResRow[3])) <> 0 then
//узел не корневой
begin
//ищем родителя
Nod := FindTreeNode(CatsView.TopItem,StrToInt(VarToStr(ResRow[3])));
//если родитель не найден, то родителем создаваемого узла у тебя станет черт-те какой узел, но только не тот который должен быть
TTreeNode(Tree.Items.AddChild(Nod,VarToStr(ResRow[4]))).Data :=
Pointer(StrToInt(VarToStr(ResRow[0]))); // Добавляет под....
end;
Нужен рекурсивный алгоритм, и одним SQL-запросом в общем случае не обойтись: для каждого "родителя" должен осуществляться SQL-запрос его "детей". Самый первый запрос должен вернуть корневые узлы, от которых и пойдет дальнейшая пляска
ДьяволСД (2006-10-18 10:55:00) [7]Я всё-таки енто сделал :) Если кому интересно, вот код:
procedure TMainForm.CatListFill(Tree: TTreeView);
var
Nod:TTreeNode;
Function FindTreeNode(FirstNode: TTreeNode; Const Pointid: integer): TTreeNode;
Begin
Result:= FirstNode;
While Result <> Nil Do
Begin
If Integer(Result.Data) = Pointid Then Exit;
Result:= Result.GetNext;
End;
End;
begin
ResRow:=DB.exec('SELECT * FROM mag_categories WHERE cattype <> '+onequote+
'Deleted'+onequote+' ORDER BY `name` ASC');
Tree.Items.BeginUpdate;
Tree.SortType:=TSorttype(stNone);
while not ResRow.eof do
begin
if StrToInt(VarToStr(ResRow[3])) = 0 then
begin
TTreeNode(Tree.Items.Add(nil,VarToStr(ResRow[4]))).Data :=
Pointer(StrToInt(VarToStr(ResRow[0]))); //Корневые ноды
end
else if StrToInt(VarToStr(ResRow[3])) <> 0 then
begin
Nod := FindTreeNode(CatsView.TopItem,StrToInt(VarToStr(ResRow[3])));
TTreeNode(Tree.Items.AddChild(Nod,VarToStr(ResRow[4]))).Data :=
Pointer(StrToInt(VarToStr(ResRow[0]))); // Добавляет под....
end;
ResRow.next
end;
Tree.Items.EndUpdate;
end;
Всем спасибо :)))
Сергей М. (2006-10-18 09:49:00) [8]
> как интегер в поинте сохранить ентом?
SomeTreeNode.Data := Pointer(12345);
ДьяволСД (2006-10-18 09:27:00) [9]Сергей М.
А не подскажите как интегер в поинте сохранить ентом? Где-то проскакивало, найти не могу :(
ДьяволСД (2006-10-18 09:22:00) [10]вообщем так я получаю данные
ResRow:=DB.exec('SELECT * FROM mag_categories ORDER BY `name` ASC');
while not ResRow.eof do
begin
cols:=ResRow.fieldcount;
v:=ResRow[4]; // 1 - Catid, 3 - parentid, 4 - name
a1:=VarToStr(v);
CatsView.Items.AddChildFirst(nil,a1); // сделал тестовое заполнение корня
ResRow.next
end
Сергей М. (2006-10-18 09:15:00) [11]
> ДьяволСД (18.10.06 09:00) [2]
Абракадабра какая-то ...
> как ID дополнительно хранить?
>
Например, в св-ве TTreeNode.Data
ДьяволСД (2006-10-18 09:08:00) [12]Хотяб подскажите как ID дополнительно хранить?
ДьяволСД (2006-10-18 09:00:00) [13]У меня база не через гриды таблицы и т.д. проходит. Я с базой работаю через юнит (мне так проще) соответственно привязать к DBTreeView не смогу
Сергей М. (2006-10-18 08:53:00) [14]
> Мне из базы нужно заполнить TreeView
DBTreeView чем не угодил ?