Selection
The Interaction guide covers the user-facing selection
switches — MultiSelect, ShowSelection, KeepSelection. This guide covers the
programmatic side: how to read what is selected, select items from code,
select a whole batch by criteria, and veto or react to selection changes. Reach
for this when the app drives the selection itself — a "select all overdue", a
master/detail panel that follows the selection, or a bulk recolor/delete over the
chosen items. The current selection is exposed as a live
TTMSFNCPlannerSelectedItems list
(TList<TTMSFNCPlannerItem>), so reading and iterating it is just list code.
Enabling multi-select
A single click always selects one item. To hold more than one in the selection,
turn on Interaction.MultiSelect first — every example below assumes it is on:
{ Inside your form's OnCreate event: }
Planner1.Interaction.MultiSelect := True;
With MultiSelect off, SelectItem still works but each call replaces the
previous selection rather than extending it.
Selecting items in code
The planner exposes two ways to select:
SelectItem(AItem)/SelectItem(AItemIndex)— add one item, by instance or by index.SelectItems(AItems)— add several at once.AItemsis aTTMSFNCPlannerItemArray, which is an array of item indexes (array of Integer), not an array of item objects.UnselectAllItemsclears the selection.
This example clears the selection, then walks the Items collection and selects
every appointment that starts before noon, and shows the index-based overload:
procedure TForm1.SelectMorningMeetings;
var
i: Integer;
it: TTMSFNCPlannerItem;
begin
// Multi-select must be on before more than one item can be selected.
Planner1.Interaction.MultiSelect := True;
Planner1.BeginUpdate;
try
// Start from a clean selection.
Planner1.UnselectAllItems;
// Select every item that starts before noon by walking the Items collection.
for i := 0 to Planner1.Items.Count - 1 do
begin
it := Planner1.Items[i];
if Frac(it.StartTime) < 0.5 then // 0.5 = 12:00
Planner1.SelectItem(it); // overload taking the item instance
end;
finally
Planner1.EndUpdate;
end;
// SelectedItems is a live TList<TTMSFNCPlannerItem> — read it back.
Caption := Format('%d morning item(s) selected', [Planner1.SelectedItems.Count]);
end;
procedure TForm1.SelectFirstThreeByIndex;
var
indexes: TTMSFNCPlannerItemArray; // = array of Integer (item indexes)
begin
// SelectItems takes item indexes, not item objects.
indexes := [0, 1, 2];
Planner1.SelectItems(indexes);
end;
Read the result back through SelectedItems — it always reflects the current
state, whether the user or your code made the selection.
Vetoing and reacting to changes
Two events bracket every selection change:
OnBeforeSelectItemfires first with avar ACanSelect— set it toFalseto block the item from being selected at all.OnAfterSelectItemfires once the item is selected, with the item as its parameter — the place to update a details panel.
procedure TForm1.WireSelectionEvents;
begin
Planner1.OnBeforeSelectItem := PlannerBeforeSelectItem;
Planner1.OnAfterSelectItem := PlannerAfterSelectItem;
end;
procedure TForm1.PlannerBeforeSelectItem(Sender: TObject;
AItem: TTMSFNCPlannerItem; var ACanSelect: Boolean);
begin
// Refuse selection of read-only items. Setting ACanSelect to False
// cancels the selection before it happens.
if not AItem.Editable then
ACanSelect := False;
end;
procedure TForm1.PlannerAfterSelectItem(Sender: TObject;
AItem: TTMSFNCPlannerItem);
begin
// Fires once the selection has been applied. AItem is the item just selected.
if Assigned(AItem) then
begin
LabelTitle.Text := AItem.Title;
LabelWhen.Text := Format('%s - %s',
[TimeToStr(AItem.StartTime), TimeToStr(AItem.EndTime)]);
end;
end;
Putting it together
This combines the pieces into one workflow: enable multi-select, install a veto so
locked items can never be selected, select a batch by criteria, then run a bulk
operation that reads SelectedItems and recolors every chosen item:
procedure TForm1.ColorSelectedItems;
var
i: Integer;
begin
// Recolor every currently selected item. SelectedItems is read live, so this
// works whether the user selected with the mouse or the code selected by
// criteria (see SelectMorningMeetings).
Planner1.BeginUpdate;
try
for i := 0 to Planner1.SelectedItems.Count - 1 do
Planner1.SelectedItems[i].Color := gcTomato;
finally
Planner1.EndUpdate;
end;
end;
procedure TForm1.SetUpSelectionWorkflow;
begin
// 1. Allow multiple items to be selected at once.
Planner1.Interaction.MultiSelect := True;
// 2. Block locked items from ever entering the selection.
Planner1.OnBeforeSelectItem := PlannerBeforeSelectItem;
// 3. Select a batch by criteria, then act on the whole selection at once.
SelectMorningMeetings;
ColorSelectedItems;
end;
Pitfalls
SelectItemstakes indexes, not items.TTMSFNCPlannerItemArrayisarray of Integer. Pass[0, 1, 2](item indexes); passing item objects will not compile. UseSelectItem(AItem)when you have the instance.- Multi-select must be on to accumulate. With
Interaction.MultiSelect = False, eachSelectItemreplaces the selection — a loop ends with only the last item selected. SelectedItemsis non-owning. It tracks the selection; never free items through it. Add and remove items through theItemscollection.- Batch programmatic selection. Wrap a selection loop in
BeginUpdate/EndUpdateso the planner repaints once, not after everySelectItem. - A vetoed item never reaches
OnAfterSelectItem. IfOnBeforeSelectItemsetsACanSelect := False, the after event does not fire for that item.
Related API
TTMSFNCPlanner—SelectedItems,SelectItem,SelectItems,UnselectAllItems,OnBeforeSelectItem,OnAfterSelectItem,ItemsTTMSFNCPlanner.Interaction—MultiSelect,ShowSelection,KeepSelection
See also
- Interaction — the user-facing selection switches
- Items — the
Itemscollection and per-item properties - Appearance — styling the selection overlay and selected items