Is there a way to delete all children from a TTreeViewItem? I tried DeleteChildren
but that causes crashes.
What I thought what was a simple question turns out to generate many more questions. That's why I explain of what I am trying to do.
My application tries to generate a directory tree in Delphi XE5 FMX. I use TTreeView for that. It starts by generating a list of drives, all of them TTreeViewItem's owned by TTreeView. When the user clicks on an item the directories below are added to the directory and the TTreeViewItem clicked upon expands. When the user clicks again the TTreeViewItem callapses. This has one caveat: the next time the user clicks on the same TTreeViewItem, the list of directories are added to the existing ones, see image below. In order to prevent that I would like to first clear the current list.
When I tried to delete the children using TreeViewItem.DeleteChildren from a TTreeViewItem I get an exception at another spot, see the picture below.
As to some questions: yes, I am sure I only add TTreeViewItems and this is the only Control I assign the OnClick event (import_directory_click). I have added the complete code and commented out the non-essentials to be sure.
I hope somebody tells me this functionality already exists (couldn't find it) but even then I would still like to know how to manage a TTreeView.
procedure TMain.import_initialize;
var
Item: TTreeViewItem;
drive: Char;
start: string;
begin
Directory_Tree.Clear;
{$IFDEF MSWINDOWS}
// When Windows, just present a list of all existing drives
for drive := 'C' to 'Z' do
begin
// A drive exists when its root directory exists
start := drive + ':\';
if TDirectory.Exists (start) then import_add (start, Directory_Tree);
end; // for
{$ELSE}
// All other systems are unix systems, start with root.
drive := '/';
start:= drive;
Item := import_add (TPath.GetPathRoot (start), DirectoryTree);
import_get_dirs (Item, start);
{$ENDIF}
start := TPath.GetSharedPicturesPath;
import_add (start, Directory_Tree);
if start <> TPath.GetPicturesPath
then import_add (TPath.GetPicturesPath, Directory_Tree);
// import_test_selection ('');
end; // import_initialize //
procedure TMain.import_directory_click (Sender: TObject);
var
TreeItem: TTreeViewItem;
obj: TFMXObject;
first_file: string;
begin
GridPanelLayout.Enabled := False;
if Sender <> nil then
begin
TreeItem := Sender as TTreeViewItem;
if TreeItem.IsExpanded then
begin
TreeItem.CollapseAll;
end else
begin
TreeItem.DeleteChildren; // <== this statement
import_get_dirs (TreeItem, TreeItem.Text);
{
first_file := find_first (TreeItem.Text, Selected_Images);
if first_file <> '' then
begin
Image.Bitmap.LoadFromFile (first_file);
GridPanelLayout.Enabled := True;
end; // if
}
TreeItem.Expand; // <== causes an exception over here
end; // if
end; // if
end; // import_directory_click //
procedure TMain.import_get_dirs (Start_Item: TTreeViewItem; start: string);
var
DirArray: TStringDynArray;
DirArraySize: Int32;
i: Int32;
begin
DirArray := TDirectory.GetDirectories (start);
DirArraySize := Length (DirArray);
for i := 0 to DirArraySize - 1
do import_add (DirArray [i], Start_Item);
end; // get_dirs //
function TMain.import_add (dir: string; owner: TControl): TTreeViewItem;
var
TreeItem: TTreeViewItem;
begin
TreeItem := TTreeViewItem.Create (owner);
TreeItem.text := dir;
TreeItem.OnClick := import_directory_click;
// TreeItem.Parent := owner;
owner.AddObject (TreeItem);
Result := TreeItem;
end; // import_add //
It seems that TreeItem.DeleteChildren deletes the item content site instead of the subitems. I suggest to use this:
for i := TreeItem.Count - 1 downto 0 do
TreeItem.RemoveObject(TreeItem.Items[i]);