Наследование свойств класса имеет последствия: невозможность редактирования унаследованных свойств. И это правильно: редактирование должно производиться только там, где были объявлено данное свойство. Но в конструкторе Data Keeper некоторые параметры свойства класса могут отличаться у разных классов, например видимость и порядок следования свойства в табличном представлении списка объектов. Или наличие детализации. Получается, что у свойства класса должны быть независимые параметры для каждого класса.
![](https://k245.ru/wp-content/uploads/2023/10/image-14.png)
Этого можно добиться, если добавить ещё одну таблицу vproperty и перенести в неё такие параметры, как порядок следования, видимость и другие, которые нам понадобятся в скором времени для улучшения алгоритма генерации формы редактирования.
![](https://k245.ru/wp-content/uploads/2024/05/image-17.png)
Изменения структуры данных потребовало не только переписать код скриптов и SQL-запросы, но и решить вопрос с формой редактирования свойств класса. Обычно в MVDB для каждой таблицы используется отдельная форма редактирования. Но в нашем случае это было бы не удобно для пользователя. Поэтому я решил “вклеить” одну форму редактирования в другую с помощью процедуры Form_ShowOnWinControl() из модуля VClass\Forms.pas.
![](https://k245.ru/wp-content/uploads/2024/05/image-18-1024x466.png)
На основной форме редактирования efmCProperty (1) добавляем панель panVProperty (2), размер которой должен быть таким, чтобы на ней поместилась дополнительная форма редактирования efmVProperty. Точнее – та часть формы, на которой находится элемент grbView, содержащий компоненты для редактирования таблицы vproperty.
![](https://k245.ru/wp-content/uploads/2024/05/image-19.png)
На форме efmVProperty кроме группы с компонентами для редактирования параметров свойств (1), находятся невидимые поля (2), связывающие форму со свойством (edtIDCProperty) и классом (edtIDClass). Кнопка btnSave (3) спрятана за группу grbView – если сделать её невидимой, то её нельзя будет “нажать” с помощью скрипта. Её свойство Action (4) настроено на сохранение данных (5) в таблицу vproperty (6). Обязательно снимите флажок “Закрыть текущую форму после сохранения”, чтобы форма efmVProperty оставалась видимой внутри формы efmСProperty.
Привязку выполняем в процедуре UserApp_InitForm:
...
Form_ShowOnWinControl( efmVProperty, efmCProperty.panVProperty ); // вторая половина формы редактирования
...
Code language: Delphi (delphi)
Обработчик onShow для формы efmCProperty необходимо немного доработать. Для того, чтобы данные на дополнительной форме прогрузились из базы, нужно найти ID записи, которая вычисляется с помощью запроса. Либо проинициализировать форму для добавления новой записи. для этого я добавил вспомогательную процедуру NewRecord.
Здесь же находится блокировка редактирования основных данных для случая, если мы открыли форму редактирования унаследованного свойства класса.
procedure efmCProperty_OnShow (Sender: TObject; Action: string);
// отображение формы редактирования свойств класса
var
tmpID: integer;
tmpSQL: string;
procedure NewRecord;
// новая запись
begin
efmVProperty.NewRecord('vproperty');
efmVProperty.edtIDClass.Text := frmCProperty.edtIDClass.Text;
efmVProperty.edtCaption.Text := efmCProperty.edtName.Text;
// добавить номер параметра
efmVProperty.edtGridOrderNum.Value := frmCProperty.tgrMain.RowCount + 1;
efmVProperty.edtFieldOrderNum.Value := frmCProperty.tgrMain.RowCount + 1;
end;
begin
if Action = 'NewRecord' then
begin // новая запись
// основные свойства
efmCProperty.edtClassID.Value := frmCProperty.edtIDClass.Value;
if frmCProperty.tgrMain.RowCount = 0 then // не очень очевидный случай - первое свойство - имя для отображения...
efmCProperty.chbIsName.Checked := True;
efmCProperty.cmbPType.dbItemID := 1;
// вспомогательные
NewRecord;
end
else
begin // существующая запись - загрузить доп. данные
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;
// редактировать элементы структуры можно только при редактировании класса, где они объявлены
if frmCProperty.edtIDClass.Text = efmCProperty.edtClassID.Text then
begin
efmCProperty.grbStructure.Caption := ' Структура ';
efmCProperty.grbStructure.Enabled := True;
efmCProperty.edtName.SetFocus;
end
else
begin
efmCProperty.grbStructure.Caption := ' Структура (просмотр) ';
efmCProperty.grbStructure.Enabled := False;
efmVProperty.edtCaption.SetFocus;
end;
end;
Code language: Delphi (delphi)
Вторая доработка касается кнопки сохранения данных основной формы редактирования. Необходимо добавить обработчик события onAfterClick, в котором вызвать сохранение данных на дополнительной форме.
procedure efmCProperty_btnSave_OnAfterClick (Sender: TObject);
begin
efmVProperty.edtIDCProperty.Value := efmCProperty.btnSave.dbGeneralTableId; // связываем
efmVProperty.btnSave.Click; // сохраняем
efmCProperty.Close; // предыдущая команда сбивает MVDB с толку, поэтому нужно закрывать форму
end;
Code language: JavaScript (javascript)
Итоги
Возможно, такое решение кому-то покажется сложным: вместо комбинирования форм можно было выполнить добавление или редактирование данных в таблице vproperty с помощью SQL-запросов и скриптов, но я старался минимизировать код, который придется менять в случае каких-либо доработок, и по максимуму использовать возможности самого MVDB.
![](https://k245.ru/wp-content/uploads/2024/05/image-20-1024x645.png)
Добавлена блокировка редактирования структуры, если свойство класса унаследовано (1). Параметры отображения (2) привязываются к классу. Добавлено раздельное управление порядка следования, видимости и ширины для табличного представления (3) и для компонентов на форме редактирования (4).