Inheriting class properties has consequences: the inability to edit inherited properties. And this is correct: editing should only be done where this property was declared. But in the Data Keeper designer, some class property parameters may differ between classes, for example, the visibility and order of the property in the table view of the list of objects. Or the presence of detail. Therefore, a class property must have independent parameters for each class.
![](https://k245.ru/wp-content/uploads/2023/10/image-14.png)
This can be achieved by adding another vproperty table and transferring to it parameters such as ordering, visibility and others that we will need soon to improve the editing form generation algorithm.
![](https://k245.ru/wp-content/uploads/2024/05/image-17.png)
Changing the data structure required not only rewriting the script code and SQL queries, but also resolving the issue with the form for editing class properties. Typically, MVDB uses a separate editing form for each table. But in our case it would not be convenient for the user. Therefore, I decided to “paste” one editing form into another using the Form_ShowOnWinControl() procedure from the VClass\Forms.pas module.
![](https://k245.ru/wp-content/uploads/2024/05/image-18-1024x466.png)
On the main efmCProperty editing form (1), add a panVProperty panel (2), the size of which should be such that it can accommodate the additional efmVProperty editing form. More precisely, that part of the form on which the grbView element is located, containing components for editing the vproperty table.
![](https://k245.ru/wp-content/uploads/2024/05/image-19.png)
On the efmVProperty form, in addition to the group with components for editing property parameters (1), there are invisible fields (2) that connect the form with a property (edtIDCProperty) and a class (edtIDClass). The btnSave button (3) is hidden behind the grbView group – if you make it invisible, then it cannot be “clicked” using the script. Its Action property (4) is configured to save data (5) to the vproperty table (6). Be sure to clear the “Close current form after saving” checkbox to ensure that the efmVProperty form remains visible within the efmCProperty form.
We perform the binding in the UserApp_InitForm procedure:
...
Form_ShowOnWinControl( efmVProperty, efmCProperty.panVProperty ); // second half of the editing form
...
Code language: Delphi (delphi)
The onShow handler for the efmCProperty form needs some modification. In order for the data on the additional form to be loaded from the database, you need to find the ID of the record, which is calculated using the query. Or initialize the form to add a new entry. To do this I added a helper procedure NewRecord.
There is also a blocking for editing the main data in case we have opened a form for editing an inherited class property.
procedure efmCProperty_OnShow (Sender: TObject; Action: string);
// displaying the form for editing class properties
var
tmpID: integer;
tmpSQL: string;
procedure NewRecord;
// new entry
begin
efmVProperty.NewRecord('vproperty');
efmVProperty.edtIDClass.Text := frmCProperty.edtIDClass.Text;
efmVProperty.edtCaption.Text := efmCProperty.edtName.Text;
// add parameter number
efmVProperty.edtGridOrderNum.Value := frmCProperty.tgrMain.RowCount + 1;
efmVProperty.edtFieldOrderNum.Value := frmCProperty.tgrMain.RowCount + 1;
end;
begin
if Action = 'NewRecord' then
begin // new entry
// basic properties
efmCProperty.edtClassID.Value := frmCProperty.edtIDClass.Value;
if frmCProperty.tgrMain.RowCount = 0 then // not a very obvious case - the first property is the name to display...
efmCProperty.chbIsName.Checked := True;
efmCProperty.cmbPType.dbItemID := 1;
// auxiliary
NewRecord;
end
else
begin // existing record - load additional. data
tmpSQL := 'SELECT id FROM vproperty WHERE id_class = '+frmCProperty.edtIDClass.Text+' AND id_cproperty = '+IntToStr(efmCProperty.btnSave.dbGeneralTableId);
tmpID := SQLExecute( tmpSQL ) ;
if tmpID = 0 then
NewRecord
else
efmVProperty.ShowRecord('vproperty',tmpID);
end;
// you can edit structure elements only when editing the class where they are declared
if frmCProperty.edtIDClass.Text = efmCProperty.edtClassID.Text then
begin
efmCProperty.grbStructure.Caption := 'Structure';
efmCProperty.grbStructure.Enabled := True;
efmCProperty.edtName.SetFocus;
end
else
begin
efmCProperty.grbStructure.Caption := 'Structure (view)';
efmCProperty.grbStructure.Enabled := False;
efmVProperty.edtCaption.SetFocus;
end;
end;
Code language: Delphi (delphi)
The second improvement concerns the button for saving data in the main editing form. It is necessary to add an onAfterClick event handler in which to cause data to be saved on an additional form.
procedure efmCProperty_btnSave_OnAfterClick(Sender: TObject);
begin
efmVProperty.edtIDCProperty.Value := efmCProperty.btnSave.dbGeneralTableId; // connect
efmVProperty.btnSave.Click; // save
efmCProperty.Close; // the previous command confuses MVDB, so we need to close the form
end;
Code language: JavaScript (javascript)
Results
This solution may seem complicated to some: instead of combining forms, it was possible to add or edit data in the vproperty table using SQL queries and scripts, but I tried to minimize the code that would have to be changed in case of any modifications, and to the maximum use the capabilities of MVDB itself.
![](https://k245.ru/wp-content/uploads/2024/05/image-20-1024x645.png)
Added blocking of structure editing if a class property is inherited (1). Display parameters (2) are bound to the class. Added separate controls for the order, visibility and width for the table view (3) and for components on the editing form (4).