Custom Item Classes
Most responsive lists are built entirely from conditions, templates, and the
built-in item properties (HeaderText, Content, FooterText, Values).
Reach for a custom item class only when an item needs extra state that the
built-in properties cannot hold, or when it must draw something the template
system does not express — a status badge, a progress ring, a sparkline, or a
state-dependent overlay. A custom item class lets you add published properties
for that extra state and override DrawItem to paint it on top of the standard
template, header, and footer rendering. You opt in by deriving a list class that
overrides GetItemClass so every item the list creates is your custom type.
This guide shows how to define the class, draw custom content, and combine both
with the responsive conditions that reflow the list across breakpoints.
Define a Custom Item Class
Derive from TResponsiveListItem and add the published properties your item
needs. Publishing the property keeps it available to the designer and to
streaming. Then derive a list class from TTMSFNCResponsiveList and override
GetItemClass to return your item type — this is the hook the list uses when it
creates new items, so every Items.Add produces an instance of your class.
type
TStatusResponsiveListItem = class(TResponsiveListItem)
private
FStatusText: string;
published
property StatusText: string read FStatusText write FStatusText;
end;
TStatusResponsiveList = class(TTMSFNCResponsiveList)
protected
function GetItemClass: TCollectionItemClass; override;
end;
Custom Drawing
Override the item DrawItem method to paint additional content after the
inherited rendering has drawn the standard template, header, and footer. Call
inherited first so the built-in visuals are in place, then draw only the extra
state — keep custom drawing focused on what the templates cannot express.
type
TStatusResponsiveListItem = class(TResponsiveListItem)
private
FStatusText: string;
protected
procedure DrawItem(AGraphics: TTMSFNCGraphics; ATemplate, AHeaderTemplate,
AFooterTemplate: string; ARect: TRect; Focus: Boolean); override;
published
property StatusText: string read FStatusText write FStatusText;
end;
TStatusResponsiveList = class(TTMSFNCResponsiveList)
protected
function GetItemClass: TCollectionItemClass; override;
end;
procedure TStatusResponsiveListItem.DrawItem(AGraphics: TTMSFNCGraphics;
ATemplate, AHeaderTemplate, AFooterTemplate: string; ARect: TRect;
Focus: Boolean);
begin
inherited DrawItem(AGraphics, ATemplate, AHeaderTemplate, AFooterTemplate,
ARect, Focus);
AGraphics.DrawText(ARect, StatusText);
end;
function TStatusResponsiveList.GetItemClass: TCollectionItemClass;
begin
Result := TStatusResponsiveListItem;
end;
Keep custom drawing focused on item-specific visuals. Use normal conditions and templates for layout changes, then draw only the extra visual state that is not covered by the built-in item properties.
Combining custom drawing with responsive conditions
A custom item class does not replace responsive layout — it composes with it.
The list still reflows your custom items across breakpoints. The following
example defines a status item that paints its StatusText, then configures
single-column and three-column conditions and adds items that set the custom
state:
type
TStatusResponsiveListItem = class(TResponsiveListItem)
private
FStatusText: string;
protected
procedure DrawItem(AGraphics: TTMSFNCGraphics; ATemplate, AHeaderTemplate,
AFooterTemplate: string; ARect: TRect; Focus: Boolean); override;
published
property StatusText: string read FStatusText write FStatusText;
end;
TStatusResponsiveList = class(TTMSFNCResponsiveList)
protected
function GetItemClass: TCollectionItemClass; override;
end;
procedure TStatusResponsiveListItem.DrawItem(AGraphics: TTMSFNCGraphics;
ATemplate, AHeaderTemplate, AFooterTemplate: string; ARect: TRect;
Focus: Boolean);
begin
inherited DrawItem(AGraphics, ATemplate, AHeaderTemplate, AFooterTemplate,
ARect, Focus);
if StatusText <> '' then
AGraphics.DrawText(ARect, StatusText);
end;
function TStatusResponsiveList.GetItemClass: TCollectionItemClass;
begin
Result := TStatusResponsiveListItem;
end;
{ Custom drawing (above) reflowed by responsive conditions (below): }
procedure TForm1.ConfigureStatusList(AList: TStatusResponsiveList);
var
Condition: TResponsiveCondition;
Item: TResponsiveListItem;
begin
AList.Conditions.Clear;
Condition := AList.Conditions.Add;
Condition.WidthFrom := 0;
Condition.WidthTo := 360;
Condition.Columns := 1;
Condition.ItemHeight := 120;
Condition := AList.Conditions.Add;
Condition.WidthFrom := 361;
Condition.WidthTo := -1;
Condition.Columns := 3;
Condition.ItemHeight := 120;
AList.Items.Clear;
Item := AList.Items.Add;
Item.HeaderText := 'Support';
Item.Content := '<b>Open tickets</b><br>12 items need review';
(Item as TStatusResponsiveListItem).StatusText := 'SLA breach risk';
Item := AList.Items.Add;
Item.HeaderText := 'Sales';
Item.Content := '<b>Pipeline</b><br>4 opportunities closing';
(Item as TStatusResponsiveListItem).StatusText := 'On track';
end;
Common pitfalls
- Forgetting
GetItemClass. Adding a custom item class is not enough — the list only creates your type if a list descendant overridesGetItemClass. Without it,Items.Addreturns a plainTResponsiveListItemand the cast in your setup code fails. - Drawing before
inherited. Callinherited DrawItem(...)first; otherwise the standard template paints over your custom content. - Heavy work in
DrawItem.DrawItemruns on every repaint and every reflow. Compute values ahead of time and store them on the item rather than recalculating inside the draw method.