В данной статье посмотрим на алгоритм удаления при помощи Checkboxes. Суть такая же, при удалении узла нужно удалить всех его детей. Но реализация немного другая, отличная от той, где мы удаляли через Selection. Алгоритм, прямо скажу, не быстрый, но рабочий. Вообще, всё что на TreeView ограничивается несколькими сотнями узлов – дальше начинает критично подтормаживать, при переподчинении узлов, удалении и так далее.
Идея алгоритма в том, что мы идем с конца в начало и удаляем узлы. Если в узлах есть дети, то тоже их удаляем. Алгоритм можно немного ускорить, если подсчет галочек вести в момент непосредственного нажатия на узел. При выставлении галочки – абсолютный индекс узла добавляется, при удалении удаляется, но тут надо следить за этими индексами, если допустим переместили элемент, удалили другой – те моменты, когда абсолютные индексы меняются. Поэтому я пошел самым простым, может быть не самым эффективным путем – собираю информацию об отмеченных объектах непосредственно перед удалением.
Реализация алгоритма выглядит следующим образом
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
procedure TDMDB.DeleteCheckedNodes(Sender: TObject; TreeView: TTreeView); var Node:TTreeNode; i:integer; begin //Присваиваем первый узел или выходим if TreeView.Items.GetFirstNode<>nil then Node:=TreeView.Items.GetFirstNode else exit; SetLength(CheckedNodes,0); {Выделяем только те элементы, что с галочками} repeat // Если узел отмечен галочкой, то добавляем в массив if Node.StateIndex=2 then begin SetLength(CheckedNodes,length(CheckedNodes)+1); CheckedNodes[High(CheckedNodes)]:=Node.AbsoluteIndex; end; Node:=Node.GetNext; until not Assigned(Node) ; //Выходим, если ничего не выделено if length(CheckedNodes)=0 then exit; {Непосредственно удаляем} //От последнего узла идем к первому i:=High(CheckedNodes); repeat //Удаляем всех детей while TreeView.Items.Item[CheckedNodes[i]].HasChildren do begin Node:=TreeView.Items.Item[CheckedNodes[i]].GetLastChild; while Node.HasChildren do Node:=Node.GetLastChild; DeleteRecord(Node); //Удаляем из базы TreeView.Items.Delete(Node); // Удаляем из дерева end; //Удаляем родителя DeleteRecord(TreeView.Items.Item[CheckedNodes[i]]); TreeView.Items.Item[CheckedNodes[i]].Delete; dec(i); until i=-1; // до нулевого включительно SetLength(CheckedNodes,0); //Освобождаем память end; |