Here is what the finished application will look like.
Control | Caption | Name |
TButton | Add Folder | but_AddFolder |
TButton | Add File | but_AddFile |
TButton | Remove | but_Remove |
TTreeView | tv_eg5 | |
TListView | lv_Link |
Looking at the above requirements, the most difficult is probably selecting a TreeView
node when a ListView item is double clicked. This is quite easily solved by
using the Node's ItemID property (see example 7).
As explained in example 5 I'll be using the ListView's data property as if it was an integer. In a real application you might want to store the ItemID value as a member of a class / record that the .Data property points to (example 5).
The way to link a ListItem to a TreeNode is to store the TreeNode's ItemID in the ListItem's data property. eg
ListView.Data := TreeNode.ItemID;Now when the ListItem is double clicked you get the node with the given TreeNode eg
LinkNode := TreeView.Items.GetNode( HTreeItem(ListView.Data) );And then select the TreeNode
LinkNode.Selected := true;As you can see its very easy. Once you get the TreeNode that the ListItem is linked to you can do whatever you like with it. Rename, delete, move etc.
Before moving on to the source, some notes on the ListView.
The source is based on example 10, so there are folder, file and root nodes.
Here is the procedure that displays the TreeNodes in the ListView.
procedure TForm1.UpdateListView; var ChildNode : TTreeNode; begin lv_Link.Items.Clear; {If nothing is selected} if( tv_eg5.Selected = nil ) then Exit; {Does this node have a parent?} if( tv_eg5.Selected.Parent <> nil ) then begin {Add the "up to parent" node} with lv_Link.Items.Add do begin Caption := 'To Parent'; {Set the image} ImageIndex := IMG_TO_PARENT; {Node that ListItem is linking to (ie Parent Node)} Data := tv_eg5.Selected.Parent.ItemId; end; end; //////////////////////////////////////////////// // Now get all the selected node's child nodes //////////////////////////////////////////////// lv_Link.Items.BeginUpdate; {Get first child} ChildNode := tv_eg5.Selected.GetFirstChild; while( ChildNode <> nil ) do begin {Add the "up to parent" node} with lv_Link.Items.Add do begin Caption := ChildNode.Text; {Set the image} ImageIndex := ChildNode.ImageIndex; {Node that ListItem is linking to} Data := ChildNode.ItemId; end; {Next child node} ChildNode := tv_eg5.Selected.GetNextChild( ChildNode ); end; lv_Link.Items.EndUpdate; end;
Nothing to complex here..
This procedure must be called whenever a change is made to the TreeView so add it to the
TreeView's OnChange event
procedure TForm1.tv_eg5Change(Sender: TObject; Node: TTreeNode); begin UpdateListView; end;
As well as to AddNode and RemoveClick
Next the ListView's OnClick event
procedure TForm1.lv_LinkDblClick(Sender: TObject); var LinkNode : TTreeNode; begin {Make sure there is a selection} if( lv_Link.Selected = nil ) then Exit; {Find the node in the TreeView that corresponds to this ListView Item} LinkNode := tv_eg5.Items.GetNode( HTreeItem(lv_Link.Selected.Data) ); {If the node was found, select it} if( LinkNode <> nil ) then LinkNode.Selected := true; end;This too is very simple.
Finally the ListView's OnEdited and OnEditing events
procedure TForm1.lv_LinkEditing(Sender: TObject; Item: TListItem; var AllowEdit: Boolean); begin {Can edit all but the "To Parent" item} AllowEdit := (Item.ImageIndex <> IMG_TO_PARENT); end;Allow any Item except for the "To Parent" item to be renames
procedure TForm1.lv_LinkEdited(Sender: TObject; Item: TListItem; var S: String); var LinkNode : TTreeNode; begin {Find the node that is being renamed} LinkNode := tv_eg5.Items.GetNode( HTreeItem(Item.Data) ); {If the node was found} if( LinkNode <> nil ) then begin {Does another node already have this name?} if( IsDuplicateName( LinkNode, s, false ) ) then begin MessageBeep( -1 ); ShowMessage( 'Duplicate Name!' ); {Revert to original name} S := Item.Caption; end else begin {Name is valid so allow rename} LinkNode.Text := s; end; end else begin {For some reason the link was not found, give ListIem its old name} S := Item.Caption; end; end;
Same as a "normal" OnEdited event, except for the Node linking. See example 9 for more information on OnEditing and OnEdited events.
Thats all there is to it. Naturally there is a lot more that can be done. For instance allowing nodes to be added or deleted in the ListView. One way to do these kind of things is to have a procedure that is called by both the ListView and TreeView events. For the TreeView you'd call DoSomthing( TreeView.Selected ) for the ListView DoSomthing( LinkNode ), where LinkNode is found as above.
All information on these www pages is copyright (©) 1997 Andre .v.d. Merwe And may not be copied or mirrored without my permission.