Customizing Event and Event recurrence dialogs
- 8 minutes to read
This topic describes how to build custom Event and Event recurrence dialogs. The ways of creating the custom fields are described for bound and unbound data modes:
Bound Mode – the data is stored in a database.
Unbound Mode – the data is stored in a file system.
Custom fields enable the data to be transferred between custom controls and storage. To specify custom fields, the TcxSchedulerDBStorage.CustomFields and TcxSchedulerStorage.CustomFields properties are used. The first property is required when the scheduler works in Bound Mode and the latter when it works in Unbound Mode.
Bound Mode
The cxSchedulerTable.db table was created in Paradox® format using the BDE toolset. To learn how to set up a connection to the data store, refer to the Bound Mode help topic.
Add four fields to the cxSchedulerTable.db table: FName, LName, Gender and Comments.
Field Name | Type | Size | |
---|---|---|---|
1 | |||
2 | |||
3 | 255 | ||
4 | |||
5 | |||
6 |
or GUID | ||
7 |
(Autoincrement) or GUID | ||
8 | |||
9 | 255 | ||
10 | 255 | ||
11 | |||
12 |
or GUID | ||
13 | |||
14 | |||
15 | |||
16 | |||
17 | |||
18 |
or TBlobField | ||
19 | |||
20 | |||
21 | |||
22 | |||
23 | |||
24 | |||
25 | FName | 255 | |
26 | LName | 255 | |
27 | Gender | 6 | |
28 | Comments | 255 |
These fields are used to persist the custom fields’ data. The FName, LName and Gender fields store the data edited by an end-user in the teFirstName, teLastName and cbGender custom editing controls (described later in this topic) located in the custom Event dialog. The Comments field stores the data edited in the teComments custom editing control located in the custom Event recurrence dialog.
To work in Bound Mode, bind the TcxSchedulerDBStorage component to the scheduler via the TcxScheduler.Storage property.
Using the Object Inspector, click the ellipsis button next to the TcxSchedulerDBStorage.CustomFields property to open the collection editor. In the collection editor, create four custom fields and bind them to the dataset fields, as shown in the following image below:
Unbound Mode
To work in Unbound Mode, bind the TcxSchedulerStorage to the scheduler via the TcxScheduler.Storage property.
Using the Object Inspector, click the ellipsis button next to the TcxSchedulerStorage.CustomFields property to open the collection editor. In the collection editor, create four custom fields, name them and then define the type of each custom field, as shown in the following image:
Note that you must pass custom field names, as they were defined in the Object Inspector, as arguments to the TcxSchedulerEvent.GetCustomFieldValueByName and TcxSchedulerEvent.SetCustomFieldValueByName methods.
Implement the TCustomForm.OnCreate and TCustomForm.OnDestroy event handlers in the main unit (the form where the scheduler is located), to use the data across multiple sessions, as shown in the following example:
unit CustomDialogsUnit;
// ...
procedure TUnboundForm.FormCreate(Sender: TObject);
const
DlgMsg = 'There was no file found';
FileName = 'c:\unbound.dat';
begin
if FileExists(FileName) then
// load the data from the file when the application starts up
Storage.LoadFromFile(FileName)
else
ShowMessage(DlgMsg);
end;
procedure TUnboundForm.FormDestroy(Sender: TObject; var Action: TCloseAction);
const
FileName = 'c:\unbound.dat';
begin
// save the data to the file when the application exits
Storage.SaveToFile(FileName);
end;
Creating custom dialogs
The event dialogs hierarchy was designed, so that a developer can use the blank dialog and populate it with the custom editing controls or benefit from the full-featured event dialog and just make minor changes to it, if required.
To use the blank event dialog or blank recurrence dialog, derive from the TcxSchedulerCustomEventEditor or TcxSchedulerCustomRecurrenceEventEditor classes.
To create custom dialogs based on the scheduler’s dialogs, create descendants of the TcxSchedulerEventEditor and TcxSchedulerRecurrenceEventEditor classes, which are responsible for the Event and Event recurrence dialog forms, respectively.
To notify the application that the custom Event and Event recurrence dialogs are to be invoked at runtime, use the cxEventEditorClass (the cxSchedulerDialogs unit) and cxRecurrenceEventEditorClass (the cxSchedulerDialogs unit) constants. See the code shown below in this topic that demonstrates how to bind descendants using these constants.
First, create the custom Event dialog:
1.To facilitate the task of building the custom Event dialog form, add the cxSchedulerEventEditor.pas (cxSchedulerEventEditor.dcu) file (in which the TcxSchedulerEventEditor class is defined) to the project, using the Add to Project dialog. To open this dialog use the Shift+F11 keys or go to the main menu and select the Project -> Add to Project… item.
2.Then create the new dialog form using the TcxSchedulerEventEditor‘s template form stored in the Object Repository. Go File -> New -> Other… in the main menu to open the New Items dialog and activate the page of your currently opened project by clicking the tab which has your project’s name, in this case CustomDialogs:
Select the cxSchedulerEventEditor icon and click the OK button. The new Event dialog form appears with its features inherited from the TcxSchedulerEventEditor parent class.
3.In the Component Palette select and drop the TcxGroupBox control (located on the Express Utilities page), three TcxLabel controls, two TcxTextEdit controls and the TcxComboBox control (located on the Express Editors page) onto the form created.
4.Using the Object Inspector, set the Caption and Name properties of the TcxGroupBox control to the Client and gbClient values, respectively. The Caption and Name properties of the three TcxLabel controls to First Name and lbFirstName, Last Name and lbLastName, Gender: and lbGender values, respectively. The Name property of the two TcxTextEdit controls to teFirstName and teLastName values, and lastly, the Name property of the TcxComboBox control to cbGender and add the female and male values to the TcxComboBoxProperties.Items property.
The following example implements the custom Event dialog:
unit CustomizedEventEditorForm;
// ...
type
TcxSchedulerEventEditorCustomized = class(TcxSchedulerEventEditor)
gbClient: TcxGroupBox;
lbFirstName: TcxLabel;
teFirstName: TcxTextEdit;
lbLastName: TcxLabel;
teLastName: TcxTextEdit;
lbGender: TcxLabel;
cbGender: TcxComboBox;
private
{ Private declarations }
protected
procedure LoadEventValuesIntoControls; override;
procedure UpdateEventValuesFromControls; override;
public
{ Public declarations }
end;
var
cxSchedulerEventEditorCustomized: TcxSchedulerEventEditorCustomized;
implementation
uses
cxSchedulerDialogs;
{$R *.dfm}
procedure TcxSchedulerEventEditorCustomized.LoadEventValuesIntoControls;
const
CLRF = #13#10;
DlgMsg = 'Can''t load data';
begin
// invoke the parent's method to load the data into the inherited editing controls located on the form
inherited LoadEventValuesIntoControls;
try
// load the data into the custom editing controls
// no checking for a null value is needed. The null value is automatically replaced with empty string in the editing controls
teFirstName.EditValue := Event.GetCustomFieldValueByName('FName');
teLastName.EditValue := Event.GetCustomFieldValueByName('LName');
cbGender.EditValue := Event.GetCustomFieldValueByName('Gender');
except
on E: Exception do
ShowMessage(DlgMsg + CLRF + E.Message);
end;
end;
procedure TcxSchedulerEventEditorCustomized.UpdateEventValuesFromControls;
const
CLRF = #13#10;
DlgMsg = 'Can''t load data';
begin
// invoke the parent's method to post the data from the inherited editing controls located on the form
inherited UpdateEventValuesFromControls;
try
// post the data from the custom editing controls
Event.SetCustomFieldValueByName('FName', teFirstName.EditValue);
Event.SetCustomFieldValueByName('LName', teLastName.EditValue);
Event.SetCustomFieldValueByName('Gender', cbGender.EditValue);
FModified := True;
except
on E: Exception do
ShowMessage(DlgMsg + CLRF + E.Message);
end;
end;
initialization
// to use the cxEventEditorClass constant, specify the cxSchedulerDialogs unit in the uses clause
// indicate that the new Event dialog will be invoked at runtime
cxEventEditorClass := TcxSchedulerEventEditorCustomized;
Note
to synchronize changes made by an end-user in the Event dialog with the storage, set the TcxSchedulerEventEditorCustomized.FModified property to True.
Repeat the above steps from 1 through to 2 to create the custom Event recurrence dialog. The TcxSchedulerRecurrenceEventEditor class is defined in the cxSchedulerRecurrenceEditor.pas (cxSchedulerRecurrenceEditor.dcu) file.
Next, drop from the Component Palette the TcxGroupBox control (located on the Express Utilities page), the TcxLabel control and the TcxTextEdit control (located on the Express Editors page) onto the form created.
Using the Object Inspector, set the Caption and Name properties of the TcxGroupBox control to the Other and gbOther values, respectively. The Caption and Name properties of the TcxLabel control to the Comments: and lbComments values, respectively and the TcxTextEdit.Name property to teComments.
The following example implements the custom Event recurrence dialog:
unit CustomizedRecurrenceEventEditorForm;
// ...
type
TcxSchedulerRecurrenceEventEditorCustomized = class(TcxSchedulerRecurrenceEventEditor)
gbOther: TcxGroupBox;
teComments: TcxTextEdit;
lbComments: TLabel;
private
{ Private declarations }
protected
procedure LoadEventValuesIntoControls; override;
procedure UpdateEventValuesFromControls; override;
public
{ Public declarations }
end;
var
cxSchedulerRecurrenceEventEditorCustomized: TcxSchedulerRecurrenceEventEditorCustomized;
implementation
uses
cxSchedulerDialogs;
{$R *.dfm}
procedure TcxSchedulerRecurrenceEventEditorCustomized.LoadEventValuesIntoControls;
const
CLRF = #13#10;
DlgMsg = 'Can''t load data';
begin
inherited LoadEventValuesIntoControls;
try
// load the data into the custom editing control
// no checking for a null value is needed. The null value is automatically replaced with empty string in the editing controls
teComments.EditValue := Event.GetCustomFieldValueByName('Comments');
except
on E: Exception do
ShowMessage(DlgMsg + CLRF + E.Message);
end;
end;
procedure TcxSchedulerRecurrenceEventEditorCustomized.UpdateEventValuesFromControls;
const
CLRF = #13#10;
DlgMsg = 'Can''t load data';
begin
inherited UpdateEventValuesFromControls;
try
// send the data from the custom editing control
Event.SetCustomFieldValueByName('Comments', teComments.EditValue);
FModified := True;
except
on E: Exception do
ShowMessage(DlgMsg + CLRF + E.Message);
end;
end;
initialization
// to use the cxRecurrenceEventEditorClass constant, specify the cxSchedulerDialogs unit in the uses clause
// indicate that the new Event recurrence dialog will be invoked at runtime
cxRecurrenceEventEditorClass := TcxSchedulerRecurrenceEventEditorCustomized;
Note
to synchronize changes made by an end-user in the Event recurrence dialog with the storage, set the TcxSchedulerRecurrenceEventEditorCustomized.FModified property to True.
Note
if you need to invoke the Event dialog and the Event recurrence dialog programmatically, use the cxShowEventEditorEx and cxShowRecurrenceEditor routines, respectively.