Blog
All Blog Posts | Next Post | Previous Post
Powerful and Intuitive Data Filtering for Delphi Developers in VCL, FMX and TMS WEB Core
Wednesday, February 26, 2025
Efficient data filtering is crucial when working with large datasets. With TTMSFNCFilterDialog, you can seamlessly apply filters to various components, including TTMSFNCDataGrid. This blog explores how to integrate TTMSFNCFilterDialog with any controlusing TTMSFNCDataGrid as an exampleto enable dynamic filtering without manual data handling.

The Advantages of TTMSFNCFilterDialog?
The TTMSFNCFilterDialog provides a visual and intuitive way to filter data, eliminating the need for users to manually construct filter conditions. By leveraging this component, you can:
- Dynamically apply filters to any component.
- Utilize a user-friendly filter dialog instead of manually setting filter conditions.
- Integrate advanced filtering logic, including AND/OR group operations and data type-based filtering.
- Customize the UI and language settings to fit your applications needs.
This control is a more flexible version of TTMSFNCDataSetFilterDialog, allowing you to filter data beyond just database datasets. In this example, we will filter simple grid data.
Setting Up TTMSFNCFilterDialog with TTMSFNCDataGrid
Step 1: Creating Sample Grid Data
First, we populate a TTMSFNCDataGrid with different types of data. For this example, we will use sample data generated by the control.
procedure TSampleForm.FormCreate(Sender: TObject); begin DataGrid.LoadSampleData; DataGrid.Columns[0].Formatting.&Type := gdftNumber; DataGrid.Columns[1].Formatting.&Type := gdftDefault; //Text DataGrid.Columns[2].Formatting.&Type := gdftDate; DataGrid.Columns[3].Formatting.&Type := gdftDefault; //Text end;
Step 2: Setting Up the Filter Dialog
Next, we create an instance of TTMSFNCFilterDialog, configure it, and retrieve the different input columns using the OnGetFilterBuilderDataColumns event.
procedure TSampleForm.FormCreate(Sender: TObject); begin DataGrid.LoadSampleData; DataGrid.Columns[0].Formatting.&Type := gdftNumber; //DataGrid.Columns[1] is Text DataGrid.Columns[2].Formatting.&Type := gdftDate; //DataGrid.Columns[3] is Text fd := TTMSFNCFilterDialog.Create(Self); fd.OnGetFilterBuilderDataColumns := DoGetFilterBuilderDataColumns; end;
fd.FilterBuilder.FormatType := fftDelphiDataSet; //Otherwise our own format type fftUniversalFilterExpressions is used.
Step 3: Mapping Filter Builder Columns
To optimize how columns are handled in the filter dialog, we map TTMSFNCDataGrid columns by assigning their names from the fixed row and their format type.
procedure TSampleForm.DoGetFilterBuilderDataColumns(Sender: TObject; AFilterBuilder: TTMSFNCFilterBuilder; ADataColumns: TTMSFNCFilterBuilderColumns);
var
I: Integer;
dt: TTMSFNCFilterBuilderDataType;
begin
ADataColumns.Clear;
for I := 0 to TMSFNCDataGrid1.Columns.Count - 1 do
begin
case DataGrid.Columns[I].Formatting.&Type of
gdftDateTime: dt := fdtDateTime;
gdftDate: dt := fdtDate;
gdftTime: dt := fdtTime;
gdftFloat: dt := fdtFloat;
gdftNumber: dt := fdtNumber;
gdftBoolean: dt := fdtBoolean;
gdftDefault: dt := fdtText;
else dt := fdtAutomatic;
end;
ADataColumns.AddColumn(TMSFNCDataGrid1.Strings[I,0], dt);
end;
end;
Step 4: Applying Filters to the Data Grid
When a user applies a filter, we validate and apply it to the TTMSFNCDataGrid.
procedure TSampleForm.ValidateFilter;
var
ia: TTMSFNCFilterValidateInputArray;
I, J: Integer;
begin
if DataGrid.ColumnCount = fd.FilterBuilder.DataColumns.Count then
begin
SetLength(ia, DataGrid.ColumnCount, DataGrid.RowCount - DataGrid.FixedRowCount);
for I := 0 to DataGrid.ColumnCount - 1 do
begin
for J := 0 to DataGrid.RowCount - DataGrid.FixedRowCount -1 do
begin
ia[I,J] := DataGrid.Cells[I,J + DataGrid.FixedRowCount];
end;
end;
oa := fd.FilterBuilder.ValidateFilterArray(ia);
SetFilter;
end;
TMSFNCDataGrid1.Repaint;
end;Alternatively, ValidateFilterRow can be used to evaluate a single row and return a Boolean indicating whether it matches the filter.
Step 5: Opening the Filter Dialog
To display the filter dialog and apply the filter:
procedure TSampleForm.FilterBtn(Sender: TObject); begin fd.Execute; ValidateFilter; end;
Step 6: Displaying the Filter Results
There are two ways to visualize the filter results: hiding non-matching rows or highlighting matching rows.
Option 1: Hiding Non-Matching Rows
procedure TSampleForm.SetFilter;
var
I: Integer;
begin
if (Length(oa) > 0) then
begin
for I := DataGrid.FixedRowCount to DataGrid.FixedRowCount + Length(oa) - 1 do
begin
if not oa[I - DataGrid.FixedRowCount] then
DataGrid.HideRow(I)
else
DataGrid.UnhideRow(I);
end;
end
else
DataGrid.UnhideAllRows;
end;Option 2: Highlighting Matching Rows
procedure TSampleForm.DataGridBeforeDrawCell(Sender: TObject; AGraphics: TTMSFNCGraphics; ACell: TTMSFNCDataGridCell; var ACanDraw: Boolean);
begin
if (ACell.Row >= DataGrid.FixedRowCount) and (Length(oa) > ACell.Row - DataGrid.FixedRowCount) then
begin
if oa[ACell.Row - DataGrid.FixedRowCount] then
AGraphics.Fill.Color := gcDarkseagreen;
end;
end;
Here you can find the full source code.
Future Implementation in TMSFNCDataGrid
This filtering feature is highly useful and should not require custom implementation for every grid.
Therefore, TTMSFNCDataGrid will include built-in support for TTMSFNCFilterDialog in a future release.
Conclusion
The TTMSFNCFilterDialog provides a powerful yet easy-to-use solution for dynamic filtering in Delphi applications. As demonstrated with TTMSFNCDataGrid, it offers a seamless integration that enhances user experience by eliminating the need for complex filtering logic.
Gjalt Vanhouwaert
This blog post has received 3 comments.
2. Wednesday, February 26, 2025 at 5:44:16 PM
A good example would be on an XData client, where we don''t always have all the records loaded, and we need to make a call the XData server according to the filter. Maybe in a future sample.
ghazali
3. Thursday, February 27, 2025 at 4:32:16 PM
@Martin, We will normally post a new blog of the combination with Aurelius next week.@ghazali, unfortunately at the moment this is not yet possible, but we are open to check what is possible. As this is currently designed for TDataSets.
Gjalt Vanhouwaert
All Blog Posts | Next Post | Previous Post

Pelletier Martin