Adding Images to a FireMonkey TreeView
If you’re familiar with the TreeView in VCL you’ll probably know that it’s possible to add an image to each item, but that that behaviour isn’t supported out of the box in FireMonkey. So, lets add the support.
There are a number of ways this could be done, but the simplest is probably by adding a TImage to the style for TTreeViewItem. A TImage contains a TBitmap which has a StyleLookup property. This property is a string which takes the StyleName of another element style element - for another TImage. What we’ll do then is simply add any images to be used to the style, and point the TImage in the style of each TreeViewItem to the one we want to use.
The Style
Start by copying the style for a TTreeViewItem (TreeViewItemStyle) and call it TreeViewImageItemStyle. The TImage needs to go in the same TLayout as the checkbox, but we want to add it inside another TLayout - this means the item can be resized while we keep the TImage at the same size.
(To copy the style element in the IDE, double click on the TTreeView in the form designer and add an item. Back out, then right click on the item and select Edit Custom Style. Make the changes and click Apply and Close).

So, add the TLayout and set the properties, Align := alLeft and Width := 20.
And add the TImage under it and set the properties, StyleName := ‘image’, Align := alCentre, WrapMode := iwStretch, HitTest := False and Height and Width := 16.
The Class
Now we need to create a custom TreeViewItem class, which we’ll call TTreeViewImageItem (note our style is TreeViewImageItemStyle). Here’s our class definition:
type TTreeViewImageItem = class(TTreeViewItem)
private
FImage: TImage;
FShowImage: Boolean;
FImageStyleLookup: String;
procedure SetShowImage(const Value: Boolean);
procedure SetImageStyleLookup(const Value: String);
protected
procedure ApplyStyle;override;
procedure FreeStyle;override;
public
constructor Create(AOwner: TComponent);override;
published
property ImageStyleLookup: String read FImageStyleLookup write SetImageStyleLookup;
property ShowImage: Boolean read FShowImage write SetShowImage default True;
end;
The property ImageStyleLookup takes the name of the style element to show as an image.
ApplyStyle and FreeStyle are pretty standard, simply fetching or nilling FImage and passing across the ImageStyleLookup.
procedure TTreeViewImageItem.ApplyStyle;
var O: TFMXObject;
begin
inherited;
O := FindStyleResource('image');
if O is TImage then
begin
FImage := TImage(O);
FImage.Visible := ShowImage;
FImage.Bitmap.StyleLookup := FImageStyleLookup;
end;
end;
procedure TTreeViewImageItem.FreeStyle;
begin
inherited;
FImage := nil;
end;
Also simple are the two property setters,
procedure TTreeViewImageItem.SetImageStyleLookup(const Value: String);
var O: TFMXObject;
begin
FImageStyleLookup := Value;
if Assigned(FImage) then
FImage.Bitmap.StyleLookup := Value;
end;
procedure TTreeViewImageItem.SetShowImage(const Value: Boolean);
begin
FShowImage := Value;
if Assigned(FImage) then
FImage.Visible := Value;
end;
Sample Application
Now we simply need to create something to test it all. Start by adding two images to the style with StyleNames of Image1 and Image2. For my test I’ve use thumbs up and thumbs down graphics.

And our test project simply has a TTreeView and a button. The button adds a new item as the child of the selected item, and sets the image to thumbs up if the index of the item is positive and thumbs down if it is negative,
procedure TForm1.Button1Click(Sender: TObject);
var Item: TTreeViewImageItem;
begin
Item := TTreeViewImageItem.Create(Self);
inc(Index);
Item.Text := 'Item'+IntToStr(Index);
if (Index mod 2) = 1 then
Item.ImageStyleLookup := 'Image1'
else
Item.ImageStyleLookup := 'Image2';
if TreeView1.Selected <> nil then
begin
Item.Parent := TreeView1.Selected;
TreeView1.Selected.IsExpanded := True;
end
else
Item.Parent := TreeView1;
end;
Enjoy.
Full source:
unit TreeViewImage;
interface
uses FMX.TreeView, FMX.Objects, FMX.Types, Classes;
type TTreeViewImageItem = class(TTreeViewItem)
private
FImage: TImage;
FShowImage: Boolean;
FImageStyleLookup: String;
procedure SetShowImage(const Value: Boolean);
procedure SetImageStyleLookup(const Value: String);
protected
procedure ApplyStyle;override;
procedure FreeStyle;override;
public
constructor Create(AOwner: TComponent);override;
published
property ImageStyleLookup: String read FImageStyleLookup write SetImageStyleLookup;
property ShowImage: Boolean read FShowImage write SetShowImage default True;
end;
implementation
{ TTreeViewImageItem }
procedure TTreeViewImageItem.ApplyStyle;
var O: TFMXObject;
begin
inherited;
O := FindStyleResource('image');
if O is TImage then
begin
FImage := TImage(O);
FImage.Visible := ShowImage;
FImage.Bitmap.StyleLookup := FImageStyleLookup;
end;
end;
constructor TTreeViewImageItem.Create(AOwner: TComponent);
begin
inherited;
ShowImage := True;
end;
procedure TTreeViewImageItem.FreeStyle;
begin
inherited;
FImage := nil;
end;
procedure TTreeViewImageItem.SetImageStyleLookup(const Value: String);
var O: TFMXObject;
begin
FImageStyleLookup := Value;
if Assigned(FImage) then
FImage.Bitmap.StyleLookup := Value;
end;
procedure TTreeViewImageItem.SetShowImage(const Value: Boolean);
begin
FShowImage := Value;
if Assigned(FImage) then
FImage.Visible := Value;
end;
end.



