Jump to content
Sign in to follow this  
Mike Torrettinni

How to get data from class to TVirtualStringTree?

Recommended Posts

I'm looking for some advice how to connect controls and class, specifically at this moment is Virtual Treeview (TVirtualStringTree - VST).


I have a class TABCFileParser that parses text files and holds all the data. I have a method that returns Strings when I want to display some data in TMemo. All good, simple.


Now I need to connect the data with VST, and I will use probably a lot of methods (OnGetText, OnGetIconImage, OnPaintText... ). Most of them will be based on data from TABCFileParser class.

Up until now, I had no problem because all data was in global variables ( no classes), I just accessed them in each VST method directly. Works good, but once you have a lot of VTSs in Main Form, it gets cluttered with all the code.


Then I 'evolved' this into enclosing data into a unit (not a class, yet) and 'exposed' all needed methods like: DataGetText, DataGetIcon... and in VST's methods I call these methods, so the VST's OnGetText has a single line, a call to this DataGetText.

This is better, since Main Form unit doesn't get cluttered and I can keep all Data related methods in 1 unit.


I was warned not to mix UI elements with data classes. So my idea to just expose ABCGetText, ABCPaintText.. and call them in VST's OnGetText with FABCFileParser.ABCGetText().. is not OK.


So, what would be sensible approach to get data from class to VST? I was thinking of a 'bridge' class that would pair up TABCFileParser and VST by pulling data from the ABC class and assign methods to VST.


Any other suggestions?


Thanks, I appreciate any kind of suggestion!



Share this post

Link to post

For such purposes I've written my own component, derived from TWinControl. It contains a TVirtualStringTree and implements all methods required to run it. For the outside world, I've implemented my own methods and properties. Within the implementation part of that unit, I've defined a Node record being used for all data handling. This record contains an implementation of a an interface:

  TAppListViewer = class(TWinControl)
  PSuperNode = ^TSuperNode;
  TSuperNode = record
    obj: IAppListItem;

IAppListItem iss defined in another unit:

    procedure SetID(const aValue: TIDType);
    function  GetID(): TIDType;
    property  ID:TIDType read GetID write SetID;

    procedure SetCaption(const aValue: string);
    function  GetCaption(): string;
    property  Caption:string read GetCaption write SetCaption;
    procedure SetParent(const aValue: IAppListItem);
    function  GetParent(): IAppListItem;
    property  Parent:IAppListItem read GetParent write SetParent;

    function  GetChildren(): TAppList;
    property  Children:TAppList read GetChildren;
    procedure AddChild(aChild: IAppListItem);
    procedure RemoveChild(aChild: IAppListItem);

My component has a property getting one such an item (the root) and all children of it. Setting it will cause a rebuilt of the tree.

    property AppList:IAppListItem read FAppList write SetAppList;



  • Thanks 1

Share this post

Link to post


Interesting, own control would be good with all the bells and whistles, instead of constantly applying same changes to new controls... would you mind sharing OnGetText/GetText method details? do you pull full rows or column item one by one from from, or have access to full data structure?

Share this post

Link to post

sure ... it's no big deal 😉 I only have two columns for this viewer: First is the caption, second the ID (for Debug purposes, usually not displayed).

procedure TAppListViewer.treeviewGetText(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
  var CellText: string);
  data: PSuperNode;
    data := treeview.GetNodeData(Node);
    case Column of
      0: CellText := data.obj.Caption;
      1: CellText := ID2String(data.obj.ID); //btw: it's TGUID, but I leave it open for other datatypes

BTW: You can also define a function in your 'IAppListItem" interface to get the string your need (e.g. function GetText(column: integer): string)

Edited by joachimd
  • Thanks 1

Share this post

Link to post

Thank you! I think I got it now. I will have a class that connects control and data, so I can attach any VST control to it, or connect any data to the control. This way will avoid cluttering the Main from with all the code.


So, when you use your control on the form, you don't have any code in the control events, right? All is defined in this interface, so if you want to see how what OnGetText contains, you have to open the unit with this interface, right?

Share this post

Link to post

Correct. My component only has a few (required) Events and Properties, but VST events are not mapped to the outside.

Share this post

Link to post

no, because my events are ways simpler 😉 btw: I use very seldom the "RAD things" ... setting all required properties and event handlers in code looks awful at first, but IMHO it results in a clearer structure of your code. I'd love to see Delphi creating code instead of DFM files (like C# does). That would make things even more simple.

  • Like 1

Share this post

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this