| 
| 
 | Вопрос # 2 530/ вопрос открыт / | 
 |  Здравствуйте, эксперты!У меня возникла проблема с заполнением компонента TreeView данными из БД. Т.е. при нажатии на кнопку дерево должно заполняться данными из БД. В базе 3 таблицы: дисциплины, темы, подтемы; связь между ними осуществляется по принципу: дисциплины--}  темы--}  подтемы (один ко многим). Заполнение TreeView должно происходить по этим же принципам. База Данных Access. Использую ADO.
 Приложение:Переключить в обычный режим  procedure TForm1.Button1Click(Sender: TObject); Var n:TTreeNode;    c:TTreeNode;    ID:Integer;    ID1:Integer; Begin DM1.DataModule2.ADOQuery1.Active:=false;DM1.DataModule2.ADOQuery1.Open;DM1.DataModule2.ADOQuery2.Active:=false;DM1.DataModule2.ADOQuery2.Open; TreeView1.Items.BeginUpdate;TreeView1.Items.Clear; While not DM1.DataModule2.ADOQuery1.Eof do  begin ID:=DM1.DataModule2.ADOQuery1DSDesigner2.Index; While not DM1.DataModule2.ADOQuery2.Eof do  begin   ID1:=DM1.DataModule2.ADOQuery2DSDesigner.Index;    if ID=ID1 then  DM1.DataModule2.ADOQuery2.Next;end; DM1.DataModule2.ADOQuery1.Next;end; TreeView1.Items.EndUpdate;end; 
|  |   Вопрос задал: Плакош Алексей (статус: Посетитель)Вопрос отправлен: 16 марта 2009, 09:13
 Состояние вопроса: открыт, ответов: 1.
 |  Ответ #1. Отвечает эксперт: Вадим К Здравствуйте, Плакош Алексей!В принципе код очень похож на правдоподобный, кроме одного - он статический.
 Суть в том, что во внутреннем цикле нужно каждый раз менять  запрос к базе. К сожалению, Вы не привели ни структуры базы, ни каких то намеков, поэтому код будет схематический. Надеюсь, что SQL Вы знаете.
 
 procedure TForm1.Button1Click(Sender: TObject);
 
Var n:TTreeNode;
    c:TTreeNode;
    ID:Integer;
    ID1:Integer;
Begin
 
DM1.DataModule2.ADOQuery1.Active:=false;
DM1.DataModule2.ADOQuery1.Open;
DM1.DataModule2.ADOQuery2.Active:=false;
 
TreeView1.Items.BeginUpdate;
TreeView1.Items.Clear;
 
While not DM1.DataModule2.ADOQuery1.Eof do
  begin
 n:=TreeView1.Items.Add (nil, DM1.DataModule2.ADOQuery1.FieldByName('Наименование').AsString);
ID:=DM1.DataModule2.ADOQuery1DSDesigner2.Index;
 
DM1.DataModule2.ADOQuery2.SQL.text := 'SELECT * FROM Mytable WHERE disciplin_id = '+inttostr(ID);
DM1.DataModule2.ADOQuery2.Open;
While not DM1.DataModule2.ADOQuery2.Eof do
  begin
   ID1:=DM1.DataModule2.ADOQuery2DSDesigner.Index;
    if ID=ID1 then
     c:=TreeView1.Items.AddChild(n, DM1.DataModule2.ADOQuery2.FieldByName('Наименование2').AsString);
 
    DM1.DataModule2.ADOQuery2.Next;
  end;
  DM1.DataModule2.ADOQuery2.Active:=false;
  DM1.DataModule2.ADOQuery1.Next;
end;
 
TreeView1.Items.EndUpdate;
end;если надо делать тройную вложенность - появиться просто ещё один вложенный цикл.
|  | Ответ отправил: Вадим К (статус: Академик)Время отправки: 16 марта 2009, 09:56
 Оценка за ответ: 5
 |  
 Мини-форум вопросаВсего сообщений: 8; последнее сообщение — 16 марта 2009, 17:21; участников в обсуждении: 4. 
|   | Плакош Алексей (статус: Посетитель), 16 марта 2009, 10:13 [#1]:Не достигнут желаемый результат, в дерево добавляються узлы с именами из 1 таблицы и 2 подузла в каждый из них, с именами 2-ух первых записей 2 таблицы... А должны добавляться только те записи, в которых значения поля из 2 таблицы совпадает со значением поля в 1. 
 Таблица 1 (Дисциплины):
 КодДисциплины
 Наименование
 Информация
 
 Таблица 2 (Темы):
 КодДисциплиныД
 КодТемы
 Наименование2
 Информация2
 
 Таблица 3 (Подтемы);
 КодТемыД
 КодПодтемы
 Наименование3
 Информация3
 
 Запрос1 (ADOQuery1):
 SELECT  Наименование, КодДисциплины
 FROM Дисциплины
 
 Запрос2(ADOQuery2):
 SELECT Наименование2, КодДисциплиныД
 FROM Темы
 
 Связь между таблицами:
 1 и 2
 По полям КодДисциплины и КодДисциплиныД
 
 2 и 3
 По полям КодТемы и КодТемыД
 
 Тип связей один-ко-многим.
 |  
|   | Тов. Женька (статус: 3-ий класс), 16 марта 2009, 10:22 [#2]:Я обычно в таких случаях делаю следующее: 1. Создаю таблицу со следующей структурой:
 ID PARENT NAME                         HasChild
 1   0          1 Корневой уровень   True
 2   0          2 Корневой уровень   True
 3   1          1 Подуровень             False
 4   1          2 Подуровень             False
 5   2          3 Подуровень             True
 6  5           4 Подуровень             False
 2. Беру компонент TdxDBTreeView и настраиваю его соответственно.
 
 А все потому, что стандартный TreeView очень медленный. Во-вторых, очень удобно "перемещать" уровни и подуровни. Вы попробуйте в стандартном TreeView поставить для записи с ID=1 поле Parent = 4.
 Конечно, это несложно побороть и самостоятельно, но TdxDBTreeView справится не хуже.
 |  
|   | Плакош Алексей (статус: Посетитель), 16 марта 2009, 10:25 [#3]:К сожалению необходим именно TreeView... Поправка, добавление необходимых тем происходит, но темы добавляться во все начальные узлы, и только те которые относятся к первой дисциплине. Остальные не добавляться.
 |  
|   | Вадим К (статус: Академик), 16 марта 2009, 11:19 [#4]:При правильном подходе TreeView очень таки быстрый. Медленный он только если обращаться по индексу. то  Плакош Алексей
 А условие where у Вас есть? или Вы надеетесь, что таблицы связаны и этого достаточно?
 Присмотрелся детальнее, строка ID:=DM1.DataModule2.ADOQuery1DSDesigner2.Index; возвращает не знаю что, надо тут подставлять ид, где то так
 ID := DM1.DataModule2.ADOQuery1.FieldByName('Коддисциплині').AsInteger
 Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Косолапов Дмитрий Юрьевич (статус: 8-ой класс), 16 марта 2009, 11:56 [#5]:В принципе для оптимизации обращений к БД (избавиться от запросов в цикле) я бы сделал один общий запрос из внутренних соединений нужных таблиц и отсортировал бы запрос нужным образом и в одном цицле по запросу анализировал бы изменения значений полей. На основании этого добавлял бы Node нужного уровня. |  
|   | Вадим К (статус: Академик), 16 марта 2009, 12:01 [#6]:Нужна ли эта оптимизация, если там десяток записей.  Для начала надо написать, что бы работало. И работало адекватно. А потом уже смотреть, что тормозить, если вообще тормозит. Галочка "подтверждения прочтения" - вселенское зло. |  
|   | Тов. Женька (статус: 3-ий класс), 16 марта 2009, 13:17 [#7]:В Интернете есть статья "DBTreeView своими руками". Очень может помочь, я думаю. |  
|   | Плакош Алексей (статус: Посетитель), 16 марта 2009, 17:21 [#8]:Огромное спасибо за помощь, ошибку нашёл. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |