Форум: "Начинающим";
Текущий архив: 2010.12.12;
Скачать: [xml.tar.bz2];
Внизработа с 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;
Скачать: [xml.tar.bz2];
Память: 0.47 MB
Время: 0.003 c