Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


Tip of the Day
Language: Pascal
Expertise: Beginner
Mar 18, 1999

Descendants of TTreeNode Not Compatible

Question:
I am having troubles with the TTreeView component and adding custom derivations of TTreeNodes to it. I want to define a new type of TTreeNode with a lot of extra parameters for my application (for example, an internal-timer for each item that does some polling, and so on) and then add that new node to a TTreeView. The problem is caused by this simplified subclass that I created of TTreeNode:
========== TUser Class ========================
type
  TUser  = Class( TTreeNode )
  private
    FSomeTimer : TTimer;

    FUserTag   : String[10];

  public
    constructor Create( AOwner: TTreeNodes ); virtual;
    destructor  Destroy; override;

    //procedure   SetTag( s : String );  not relevant in example
  end;

 { procedures follow }

constructor TUser.Create( AOwner : TTreeNodes );
begin
 inherited Create( AOwner );

 FSomeTimer := TTimer.Create( nil );
 FSomeTimer.Enabled := FALSE;
end;

destructor TUser.Destroy;
begin
 
 inherited Destroy;
 FSomeTimer.Free;
end; 

====================END TUser Class ================
When I try this next code, I receive a compiler event saying that it is not assignment compatible, which is understandable as it really isn't:
var
 aUser : TUser;

begin
 aUser := TreeView1.Items.Add( nil, 'some caption');
end;
Also, if I were to type cast the result from the .Add, it would compile but crash at run time if I attempt to modify any of my "extended" properties.

However, when I try this line of code, it does compile and work, but the item does not actually show up on screen:

 aUser := TUser.Create( TreeView1.Items );
How can I solve this problem? Do I need to create some new type of TTreeView? If so, how is this possible?

Answer:
Think about this: When you make a call to the Add method, what by default gets created? A TTreeNode. TTreeView knows only about how to create a TTreeNode, not a descendant. That's where your problem lies. If you look at the ComCtrls unit, you'll see that TTreeView merely surfaces various protected properties of TCustomTreeView, and if you look at the code for AddChild of TCustomTreeView.Items.AddChild (or Add, etc.), you'll see that this method creates new TTreeNodes. No matter what you try to do, you won't be able to create the descendant by just calling the Add- methods. Furthermore, since TTreeNode methods cannot be overriden, you can't subclass the methods to affect some sort of polymorphic behavior. So what do you do?

You have the right idea of creating descendants, so that's a good start. What I'd do though is a bit different from what you did. Let's start with what we know. First, TCustomTreeView's Items property is of type TTreeNodes. Also, we know that TTreeNodes Add- methods create only TTreeNode objects. Furthermore, the Add- methods are static, so they can't be overridden.

Given this information, I'd make sibling objects of both TTreeNodes and TTreeNode (copy the code from both objects to create your new siblings). Yes, this is a pain, but if you want to add your own stuff without losing the default behavior, this is the way to do it. You might want to call them TExTreeNodes and TExTreeNode, respectively. They'll essentially mimic the behavior of their siblings, but have the added functionality.

Finally, you'll have to make a sibling of TCustomTreeView because of how the class handles persistence. With TCustomTreeView, it reads and writes the Items property to and from disk to save the contents of the TreeView. Unfortunately, it's expecting to read and write only TTreeNodes type. Luckily, even though you have to make a sibling, all you need to do with it is change the type Items points to your new TExTreeNodes type. You don't need to do any further coding, unless you want to add some sort of extended Items property and then you'd have to hassle with persistence from that end. Not a good idea. Oh well, that's my two-cents-worth....

DevX Pro
 
Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap