Table of Contents

Filtering

Filtering narrows the visible items without removing them from the collection. The list box offers two complementary mechanisms: an interactive header filter drop-down the user operates, and a programmatic filter collection you build from code with one or more conditions combined by logical operators. Use interactive filtering for ad-hoc exploration of a populated list; use the filter collection when the application decides what to show (a search box, a category selector, a saved view). The filtered subset is always available through FilteredItems.

Interactive header filter

Set Interaction.Filtering.Enabled := True to show a filter button at the right edge of the header. Clicking it opens a drop-down of unique values; choosing one filters the list, and the (All) entry clears it. DropDownWidth and DropDownHeight size the drop-down panel.

Enabling interactive filtering takes one property; the OnNeedFilterDropDownData handler supplies the values shown in the drop-down (omit it to let the control derive them from the item text):

procedure TForm1.EnableInteractiveFilter;
begin
  // Shows a filter button at the right of the header. The user picks a value
  // from the drop-down to filter the list; '(All)' clears the filter.
  ListBox1.Interaction.Filtering.Enabled := True;
  ListBox1.Interaction.Filtering.DropDownWidth := 160;
  ListBox1.Interaction.Filtering.DropDownHeight := 200;
end;

// Supply the values shown in the header filter drop-down.
procedure TForm1.ListBox1NeedFilterDropDownData(Sender: TObject;
  AValues: TStrings);
begin
  AValues.Add('Belgium');
  AValues.Add('France');
  AValues.Add('Germany');
end;

The capture below shows the filtered list after a value has been chosen — only the matching subset remains visible:

A list box showing only the items that match the active filter A list box showing only the items that match the active filter

Programmatic filter collection

Filter is a collection of TTMSFNCListBoxFilterData rules. Each rule has a Condition (supporting * wildcards), a CaseSensitive flag, optional Prefix/Suffix applied before matching, and an Operation that combines it with the other rules. Build the collection, then call ApplyFilter; RemoveFilters clears every rule:

procedure TForm1.ApplyContainsP;
var
  Rule: TTMSFNCListBoxFilterData;
begin
  // Build the filter collection, then apply it.
  ListBox1.Filter.Clear;
  Rule := ListBox1.Filter.Add;
  Rule.Condition := '*P*';          // wildcard match
  Rule.CaseSensitive := False;
  ListBox1.ApplyFilter;
end;

procedure TForm1.ApplyTwoConditions;
var
  Rule: TTMSFNCListBoxFilterData;
begin
  ListBox1.Filter.Clear;

  Rule := ListBox1.Filter.Add;
  Rule.Condition := 'A*';
  Rule.CaseSensitive := False;

  Rule := ListBox1.Filter.Add;
  Rule.Condition := 'B*';
  Rule.CaseSensitive := False;
  Rule.Operation := lfoOR;          // item passes when it matches A* OR B*

  ListBox1.ApplyFilter;
end;

procedure TForm1.ClearAllFilters;
begin
  ListBox1.RemoveFilters;
end;

Combining conditions

Value Description
lfoSHORT Stop at the first matching condition
lfoNONE Ignore this condition
lfoAND Item passes only when it also satisfies the previous conditions
lfoOR Item passes when it satisfies this or any previous condition
lfoXOR Item passes when it satisfies exactly one of the conditions

Reading the visible subset

After a filter is applied, FilteredItems returns the array of items currently visible, and OnFilterSelect fires when the user picks a value in the drop-down (you can adjust the chosen condition there):

{ Inside a method of your form: }
var
  I: Integer;
begin
  for I := 0 to High(ListBox1.FilteredItems) do
    Memo1.Lines.Add(ListBox1.FilteredItems[I].Text);
end;

Putting it together

Interactive and programmatic filtering coexist: keep the header drop-down enabled while applying a programmatic rule, then read FilteredItems to act on what remains visible:

procedure TForm1.ApplyCombinedFilter;
var
  Rule: TTMSFNCListBoxFilterData;
  I: Integer;
begin
  // Interactive drop-down stays available...
  ListBox1.Interaction.Filtering.Enabled := True;

  // ...while a programmatic rule narrows the list immediately.
  ListBox1.Filter.Clear;
  Rule := ListBox1.Filter.Add;
  Rule.Condition := 'A*';
  Rule.CaseSensitive := False;
  ListBox1.ApplyFilter;

  // Read back what remains visible after filtering.
  Memo1.Lines.Clear;
  for I := 0 to High(ListBox1.FilteredItems) do
    Memo1.Lines.Add(ListBox1.FilteredItems[I].Text);
end;

Pitfalls

  • RemoveFilter removes the active filter; RemoveFilters (plural) clears the entire Filter collection. Call RemoveFilters after building rules with Filter.Add to start clean.
  • Conditions use shell-style * wildcards, not SQL %.
  • Adding rules to Filter does nothing until you call ApplyFilter.
  • TTMSFNCListBoxInteraction.Filtering, Filter, ApplyFilter, RemoveFilter, RemoveFilters, FilteredItems, OnNeedFilterDropDownData, OnFilterSelect

See also

  • Interaction — sorting and selection alongside filtering
  • EventsOnNeedFilterDropDownData and OnFilterSelect wiring