Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2010.12.12;
Скачать: CL | DM;

Вниз

работа с treeview   Найти похожие ветки 

 
123456   (2010-09-20 14:10) [0]

Здравствуйте!
имеется дерево с узлами и подузлами, которое через определенный интервал времени(с помощью таймера) обновляется из базы. после обновления все узлы сворачиваются. как сохранить текущее состояние дерево, чтоб она оставалась без изменении. при обновлении дерево формируется с нуля. просто неудобно, когда рассматриваешь какой-то под узел и тут сразу обновляется и все сворачиваются, приходится все заново раскрывать.


 
Ega23 ©   (2010-09-20 14:27) [1]

Писал в своё время DBTreeView.
Сразу замечание: Не надо обновлять по таймеру. Обновлять нужно по желанию пользователя, т.е. должна быть кнопка "Обновить".

Ну а с разворачиванием-сворачиванием всё просто: запоминаешь ID открытого элемента (не Node.ID, а ID из базы).
После перестроения дерева обходишь ноды, ищешь нужный по последнему ID, ставишь его Selected. Всё что "выше" - должно само раскрыться.


 
linuxoid   (2010-09-20 14:36) [2]

вот исходник: вначале раскрываются родительские parentid=0. затем по цепочке и подузлы.
а где написать процедуру запоминания и раскрытия? придется по базе перебрать все узлы до обновления?

subjecttree.Items.BeginUpdate;
if subjecttree.Items.Count >0 then
begin
 subjecttree.Items.Clear
 end;
 basequery.Active:=false;
 basequery.SQL.Clear;
 basequery.SQL.Text:="select *"+
 "from node where parentid=:parentid";
 basequery.Parameters.ParseSQL(basequery.SQL.Text,true);
basequery.Parameters.ParamByName("parentid").Value:=0;
 try
   baseconnect.Open;
   basequery.Active:=true;

   if basequery.RecordCount<>0 then
   begin
     while not basequery.Eof do
       begin
         TreeNode:=subjecttree.Items.AddObject(nil, basequery.Fields[2].asstring,
         pointer(basequery.Fields[0].asinteger));
         subjecttree.Items.AddChildObject(TreeNode ,"" , nil);
         TreeNode.ImageIndex:=strtoint(basequery.Fields.Fields[3].asstring);
         treenode.SelectedIndex:=treenode.ImageIndex;
         basequery.Next;
       end;
     end; //if

   finally
     BaseConnect.Close; //Закрываем коннект
   end;
 SubjectTree.Items.EndUpdate; //Разрешить прорисовку

begin
 BaseQuery.Active := false;
 BaseQuery.SQL.Clear;
 //Составление запроса и ввод параметров
 //Выбираем элементы не имеющие родителя, т.е. корневые
 BaseQuery.SQL.Text := "SELECT NodeID, ParentID, NodeName, NodeType "+
                           "FROM node WHERE ParentID = :ParentID";
 BaseQuery.Parameters.ParseSQL(BaseQuery.SQL.Text, true);
 BaseQuery.Parameters.ParamByName("ParentID").Value := Integer(tn.Data);
 BaseQuery.Active := true;

 if BaseQuery.RecordCount <> 0 then
     begin
       while not BaseQuery.Eof do
       begin
         TreeNode := SubjectTree.Items.AddChildObject(tn,
                         BaseQuery.Fields[2].AsString,
                         Pointer(BaseQuery.Fields[0].AsInteger));
         TreeNode.ImageIndex:=strtoint(basequery.Fields.Fields[3].asstring);
          treenode.SelectedIndex:=treenode.ImageIndex;
         BaseQuery.Next;
       end;  //while

       Child := tn.getFirstChild;
       while Child <> nil do
         begin
             FillBranch(Child);
           Child := Child.GetNextSibling;
         end;//while

     end; //if
end; {FillBranch}


 
Ega23 ©   (2010-09-20 14:42) [3]


> а где написать процедуру запоминания и раскрытия?


Поясняю.
Если абстрагироваться от конкретных реализаций, то схема работы DB-Aware-компонентов примерно такова:
1. Сделали запрос к хранилищу данных, получили некий набор данных.
2. Перевели полученный набор данных в некую унифицированную структуру (например - в список рекордов)
3. На пользовательском компоненте отобразили видимую в данный момент часть данных.
4. Связали каждый элемент своего контрола (строчка в DBGrid, узел в TreeView и т.д.) с конкретным элементом в своей унифицированной структуре.


 
Ega23 ©   (2010-09-20 14:47) [4]

В случае TreeView нельзя никогда заранее предугадать, какой элемент будет отображён в качестве корня. Поэтому построение дерева возможно только в том случае, когда на клиент получен ВЕСЬ НД, целиком. Есть возможность задания всяких Order By, но это не совсем верно в идеологическом плане (ИМХО).

Далее. В случае дерева у тебя нет никакой гарантии того, что данные в хранилище не изменились. Т.е. даже если ты запомнишь всю "карту" раскрытых узлов, то нет никакой гарантии, что у какого-то узла не поменялся "родитель".
Поэтому, ИМХО, хранить полную карту - бессмысленно. Проще сохранять последний SelectedNodeID, после обновления НД ставить его Selected и раскрывать всё вверх до корня (ЕМНИП, в случае TTreeView это произойдёт автоматом).


 
linuxoid   (2010-09-20 15:02) [5]

можно ли по одному перебирать узлы в базе и затем проверить его в treeview на раскрытость и ставить значение в базе 0 или 1.

затем после обновления процедура сама будет проверять. по любому вначале будут раскрываться узлы, затем подузлы а дальше подподузлы. родитель подузла по любому не поменяется. подузел не будет раскрыт если его узел не раскрыт.


 
Ega23 ©   (2010-09-20 15:16) [6]


> можно ли по одному перебирать узлы в базе и затем проверить
> его в treeview на раскрытость и ставить значение в базе
> 0 или 1.


А ты возьми и сравни, что в данном случае менее затратно по времени: "сорок раз по разу" или "один раз сорок раз".
По времени будет очень долго.



Страницы: 1 вся ветка

Текущий архив: 2010.12.12;
Скачать: CL | DM;

Наверх




Память: 0.49 MB
Время: 0.008 c
15-1283459378
Юрий
2010-09-03 00:29
2010.12.12
С днем рождения ! 3 сентября 2010 пятница


2-1284972015
Max Zyuzin
2010-09-20 12:40
2010.12.12
Общий TPopupMenu для всех DBGridEh в приложении


8-1208000814
Дмитрий Белькевич
2008-04-12 15:46
2010.12.12
Сглаживание при вызове метода blt поверхности DirectX в Висте


15-1283570369
xayam
2010-09-04 07:19
2010.12.12
Движение информации и товаров


2-1284753474
mfender
2010-09-17 23:57
2010.12.12
Странности с конструктором