55[ ![ ] ( https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square )] ( #does-this-example-address-your-development-requirementsobjectives )
66<!-- default badges end -->
77
8- # DevExpress VCL Dashboards — Store Dashboard Layouts in a Database
8+ # DevExpress Dashboards for Delphi/C++Builder — Store Dashboard Layouts and State in a Database
99
10- This sample app stores a [ dashboard layout] ( https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Layout ) (XML-based template) in the BLOB field of a memory-based dataset ([ TdxMemData] ( https://docs.devexpress.com/VCL/dxmdaset.TdxMemData ) inherited from the [ TDataSet] ( https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSet ) class shipped with the standard VCL library).
10+ This example application stores [ DevExpress dashboard layouts] [ TdxCustomDashboardControl.Layout ]
11+ in a database.
12+ The sample allows users to create new layouts, modify existing layouts using the built-in
13+ Dashboard Designer, interact with dashboards, and save state or layout changes to the data source.
14+
15+ > ![ DevExpress VCL Dashboards - Database Layout Storage Example] ( ./images/vcl-dashboard-layout-database-sample-app.png )
1116
12- ![ DevExpress VCL Dashboards - Database Layout Storage Example] ( /Images/vcl-dashboard-layout-database-sample-app.png )
1317
1418## Prerequisites
1519
16- * Microsoft Windows 10 or newer
17- * Embarcadero RAD Studio IDE 12.3 (Athens) or newer (Community Edition is not supported)
18- * DevExpress VCL Components v25.2.3 or newer
20+ [ DevExpress Dashboards Prerequisites] [ req ]
21+
22+ [ req ] : https://docs.devexpress.com/VCL/405773/ExpressCrossPlatformLibrary/vcl-backend/reports-dashboards-app-deployment#vcl-reportsdashboards-prerequisites
23+
1924
2025## Test the Example
2126
@@ -26,12 +31,229 @@ This sample app stores a [dashboard layout](https://docs.devexpress.com/VCL/dxDa
26315 . Close the app. The [ TdxMemData] ( https://docs.devexpress.com/VCL/dxmdaset.TdxMemData ) component will store layout data between sessions.
27326 . Run the sample again. Click on grid records to switch between loaded dashboards.
2833
29- ![ DevExpress VCL Dashboards - Store Dashboard Layout Definitions in a Database] ( /Images/vcl-dashboards-store-layout-template-database.gif )
34+ > ![ DevExpress VCL Dashboards — Store Dashboard Layout Definitions in a Database] ( ./images/vcl-dashboards-store-layout-template-database.gif )
35+
36+
37+ ## Implementation Details
38+
39+ The example uses a DevExpress memory-based dataset for dashboard layout storage: [ TdxMemData] .
40+ You can modify the application to use any other [ TDataSet] descendant instead.
41+ To review our data module implementation, see the following file: [ uData.pas] /[ uData.cpp] .
42+
43+ The instructions assume that you start with a Delphi or C++Builder project that already includes
44+ a configured data source for DevExpress Dashboards.
45+ The example uses a memory-based dataset as the dashboard's data source
46+ (see ` mdRevenueByIndustry ` in the data module).
47+ To configure a dashboard data source in your project, refer to the following tutorial:
48+ [ Create a dashboard using the Designer Dialog] [ designer ] .
49+
50+ ### Step 1: Create a Dataset to Store Dashboard Layout and State Data
51+
52+ 1 . Add a [ TdxMemData] component to the data module (` mdLayouts ` in the example).
53+ 1 . Add a [ TDataSource] component to the data module (` dsLayouts ` in the example).
54+ Assign the previously created dataset component to ` TDataSource.DataSet ` :
55+
56+ > <img src="./images/create-bind-data-source.png" style="width: 50%"
57+ alt="Object Inspector panel displaying TDataSource properties."/>
58+
59+ 1 . Open the context menu for the dataset component and select ** Field Editor…** :
60+
61+ > <img src="./images/open-context-menu.png" style="width: 50%"
62+ alt="Context menu for the TdxMemData component displaying a 'Field Editor' option."/>
63+
64+ 1 . Click ** Add…** to create a BLOB field for layout data ([ ] ):
65+
66+ > <img src="./images/create-layout-field.png" style="width: 50%"
67+ alt="New Field dialog adding a 'Layout' field of type ftBlob"/>
68+
69+ 1 . Click ** Add…** to create a string field for layout names:
70+
71+ > <img src="./images/create-name-field.png" style="width: 50%"
72+ alt="New Field dialog adding a 'Name' field of type ftWideString"/>
73+
74+ 1 . Click ** Add…** to create another BLOB field for dashboard stats:
75+
76+ > <img src="./images/create-state-field.png" style="width: 50%"
77+ alt="New Field dialog adding a 'State' field of type ftBlob"/>
78+
79+ 1 . (* Optional* ) Preload persistent data to the dataset to make layouts available in the application upon first launch.
80+
81+ This example includes a sample dashboard layout that displays revenue data from an included dataset.
82+ You can preload the layout and revenue from [ layout.dat] and [ revenue.dat] respectively.
83+ Open the context menu for the dataset component, select ** Persistent Editor…** , click ** Load…** , and select the file.
84+
85+ > <img src="./images/create-persistent-data.png" style="width: 50%"
86+ alt="Context menu for the TdxMemData component displaying a 'Persistent Editor' option."/>
87+
88+ Alternatively, you can use the Dashboard Designer later to import dashboard data from an XML file.
89+
90+
91+ ## Step 2: Load a Dashboard Layout Definition
92+
93+ To load a layout definition to the Dashboard Control ([ TdxCustomDashboardControl] ), you must specify
94+ dashboard name ([ TdxCustomDashboardControl.DashboardName] ), layout ([ TdxCustomDashboardControl.Layout] ),
95+ and, optionally, dashboard user interaction state ([ TdxCustomDashboardControl.State] ):
96+
97+ ``` pas
98+ procedure TMainForm.LoadLayoutDefinition;
99+ begin
100+ // Ensure that the dataset has at least one record or a new record is being created:
101+ if (DataModule1.mdLayouts.RecordCount = 0) and (DataModule1.mdLayouts.State <> dsInsert) then
102+ begin
103+ dxDashboardControl1.Clear;
104+ Exit;
105+ end;
106+ // Load dashboard name and layout from the database:
107+ dxDashboardControl1.DashboardName := DataModule1.mdLayoutsName.AsString;
108+ dxDashboardControl1.Layout.Assign(DataModule1.mdLayoutsLayout);
109+ // Load dashboard state if it is stored in the database:
110+ if not DataModule1.mdLayoutsState.IsNull then
111+ dxDashboardControl1.State.Assign(DataModule1.mdLayoutsState);
112+ end;
113+ ```
114+
115+ To load a different dashboard in the Dashboard Control, assign a new dashboard name and layout.
116+ The assigned dashboard replaces the current layout definition and resets the dashboard state.
117+
118+ You can also clear the Dashboard Control using [ TdxCustomDashboardControl.Clear] .
119+
120+
121+ ### Step 3: Display the Dashboard Designer
122+
123+ Once you assigned a dashboard layout definition to the Dashboard Control,
124+ you can display the [ Dashboard Designer] [ designer ] dialog:
125+
126+ ``` pas
127+ procedure TMainForm.btnDesignClick(Sender: TObject);
128+ begin
129+ dxDashboardControl1.ShowDesigner; // Displays the Dashboard Designer
130+ end;
131+ ```
132+
133+ ### Step 4: Store Dashboard State in a Dataset
134+
135+ When a user interacts with the dashboard in the Dashboard Control or Designer,
136+ the value of [ TdxCustomDashboardControl.State] changes and an
137+ [ OnStateChanged] [ TdxCustomDashboardControl.OnStateChanged ] event is called.
138+ Handle this event to save dashboard state changes to the database.
139+
140+ ``` pas
141+ procedure TMainForm.dxDashboardControl1StateChanged(
142+ ASender: TdxCustomDashboardControl);
143+ begin
144+ // Start editing the active dataset record:
145+ DataModule1.mdLayouts.Edit;
146+
147+ // Save the current dashboard state to the active record:
148+ DataModule1.mdLayoutsState.Assign(dxDashboardControl1.State);
149+
150+ // Finish editing and post the modified record to the database:
151+ DataModule1.mdLayouts.Post;
152+ end;
153+ ```
154+
155+ ### Step 5: Store Dashboard Layouts in a Dataset
156+
157+ When a user edits and saves a dashboard in the Dashboard Designer,
158+ the value of [ TdxCustomDashboardControl.Layout] changes and an
159+ [ OnLayoutChanged] [ TdxCustomDashboardControl.OnLayoutChanged ] event is called.
160+ Handle this event to save layout changes to the database.
161+
162+ ``` pas
163+ procedure TMainForm.dxDashboardControl1LayoutChanged(
164+ ASender: TdxCustomDashboardControl);
165+ begin
166+ if DataModule1.mdLayoutsName.AsString <> dxDashboardControl1.DashboardName then
167+ begin
168+ // Create and start editing a new dataset record
169+ DataModule1.mdLayouts.Append;
170+ DataModule1.mdLayoutsName.AsString := dxDashboardControl1.DashboardName;
171+ end
172+ else
173+ // Start editing the active dataset record
174+ DataModule1.mdLayouts.Edit;
175+
176+ // Save dashboard layout to the database:
177+ DataModule1.mdLayoutsLayout.Assign(dxDashboardControl1.Layout);
178+ // Finish editing and post the modified record to the database:
179+ DataModule1.mdLayouts.Post;
180+ end;
181+ ```
182+
183+ ## Files to Review
184+
185+ - [ uData.pas] /[ uData.cpp] stores dashboard layouts and supplies data to the dashboard.
186+ - [ uMainForm.pas] /[ uMainForm.cpp] loads dashboard layouts from the data module,
187+ and displays Dashboard Control and Dashboard Designer.
188+ - [ layout.dat] and [ revenue.dat] store memory-based dataset states that you can load to reproduce this example.
189+ - [ data.dat] stores the memory-based dataset state between application sessions.
190+
30191
31192## Documentation
32193
33- * [ TdxCustomDashboardControl.Layout] ( https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Layout )
34- * [ TdxBackendDataSetJSONConnection] ( https://docs.devexpress.com/VCL/dxBackend.ConnectionString.JSON.DataSet.TdxBackendDataSetJSONConnection )
194+ - [ Introduction to VCL Dashboards] [ dashboards-intro ]
195+ - [ Tutorial: Create a dashboard using the Designer Dialog] [ designer ]
196+ - [ Use JSON as a data source for dashboards (as demonstrated in the current example)] [ json-data-source ]
197+ - [ Save dashboard layout to file on every change (code example)] [ save-to-file ]
198+ - API reference:
199+ - [ TdxCustomDashboardControl] (used to display a dashboard in an application form)
200+ - [ TdxCustomDashboardControl.State] (a JSON-based representation of dashboard state that can be stored in a BLOB data field)
201+ - [ TdxCustomDashboardControl.Layout] (an XML-based layout template that can be stored in a BLOB data field)
202+ - [ TdxCustomDashboardControl.DashboardName] (internal dashboard name that is not included in the layout or state)
203+ - [ TdxCustomDashboardControl.OnStateChanged] (event called when user interacts with a dashboard and changes its state)
204+ - [ TdxCustomDashboardControl.OnLayoutChanged] (event called when user edits and saves a dashboard in the Dashboard Designer)
205+ - [ TdxMemData] (DevExpress in-memory dataset implementation)
206+ - [ TDataSet] (contains generic database connection methods)
207+ - [ TdxBackendDataSetJSONConnection] (supplies data to dashboards)
208+
209+
210+ <!-- documentation links -->
211+
212+ [ dashboards-intro ] : https://docs.devexpress.com/VCL/405642/ExpressDashboards/vcl-dashboards
213+ [ designer ] : https://docs.devexpress.com/VCL/405774/ExpressDashboards/getting-started/create-dashboard-using-designer-dialog
214+ [ json-data-source ] : https://docs.devexpress.com/VCL/405747/ExpressCrossPlatformLibrary/vcl-backend/database-engines/vcl-backend-memory-based-data-storage
215+ [ save-to-file ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Layout#save-dashboard-layout-to-file-on-every-change
216+ [ supported-dbms ] : https://docs.devexpress.com/VCL/405703/ExpressCrossPlatformLibrary/vcl-backend/vcl-backend-supported-database-systems
217+
218+ <!-- reference links -->
219+ [ TdxCustomDashboardControl ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl
220+ [ TdxCustomDashboardControl.Clear ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Clear
221+ [ TdxCustomDashboardControl.DashboardName ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Layout
222+ [ TdxCustomDashboardControl.Layout ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.Layout
223+ [ TdxCustomDashboardControl.State ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.State
224+ [ TdxCustomDashboardControl.OnLayoutChanged ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.OnLayoutChanged
225+ [ TdxCustomDashboardControl.OnStateChanged ] : https://docs.devexpress.com/VCL/dxDashboard.Control.TdxCustomDashboardControl.OnStateChanged
226+ [ TdxBackendDataSetJSONConnection ] : https://docs.devexpress.com/VCL/dxBackend.ConnectionString.JSON.DataSet.TdxBackendDataSetJSONConnection
227+ [ TdxMemData ] : https://docs.devexpress.com/VCL/dxmdaset.TdxMemData
228+
229+
230+ <!-- external documentation links -->
231+ [ TDataSet ] : https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSet
232+ [ TDataSource ] : https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSource
233+ [ ftString ] : https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
234+ [ ftWideString ] : https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
235+ [ ftBlob ] : https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
236+
237+
238+ <!-- in-repository links -->
239+ [ uData.pas ] : ./Delphi/uData.pas
240+ [ uData.cpp ] : ./CPB/uData.cpp
241+ [ data.dat ] : ./Delphi/data.dat
242+ [ layout.dat ] : ./Delphi/layout.dat
243+ [ revenue.dat ] : ./Delphi/revenue.dat
244+ [ uMainForm.pas ] : ./Delphi/uMainForm.pas
245+ [ uMainForm.cpp ] : ./CPB/uMainForm.cpp
246+
247+
248+ ## More Examples
249+
250+ - [ Pass Hidden Parameters to a SQL Query] [ hidden-parameter-example ]
251+ - [ Generate Dashboards in a Backend / Service Application] [ non-interactive-example ]
252+ - [ Store Layouts in XML Files (DevExpress Reports for Delphi/C++Builder)] [ file-example ]
253+
254+ [ hidden-parameter-example ] : https://github.com/DevExpress-Examples/vcl-dashboards-pass-hidden-parameters-to-custom-sql-query
255+ [ file-example ] : https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file
256+ [ non-interactive-example ] : https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-database
35257
36258<!-- feedback -->
37259## Does This Example Address Your Development Requirements/Objectives?
0 commit comments