В таком случае предложу свое решение. Его плюс в том, что при наличии летающих контролов, форму не нужно перенастраивать, все делается автоматически при нажатии одной кнопки.
Опытным путем удалось установить, что летающие поля при перечислении всех контролов формы встречаются дважды. При этом "летают" только доступные для редактирования поля. Заявленная функция находит такие поля и скрывает их, добавляя вместо них эти же поля. Вообще опять же опытным путем установил, что лучше добавлять поля, чем переносить их из датагрупп. Насколько я понял, в переносе полей и кроется проблема, т.к. они начинают встречаться на форме и в новом, и в изначальном месте, id у контролов совпадает.
Дисплей-методы не летают ввиду того, что недоступны для редактирования, даже если встречаются дважды. А эдит-методы мной не тестировались.
Добавляем на форму SysSetupForm кнопку:
X++:
void clicked()
{
;
super();
sysSetupForm.upc_flyingControlsRecreate();
}
В класс SysSetupForm добавляем следующие методы:
Перечисление летающих контролов:
X++:
container upc_flyingControlNumSet()
{
Set set = new Set(Types::Integer),
flyingSet = new Set(Types::Integer);
void printControls(Object o)
{
FormBuildControl formBuildControl;
Object control;
int i;
;
for (i=1; i<=o.controlCount(); i++)
{
formBuildControl = o.controlNum(i);
control = formBuildControl;
if( set.in(formBuildControl.id()) &&
!formBuildControl.userHide() &&
this.formControlIsDataBound(control) &&
control.dataSource() &&
control.dataField() )
{
flyingSet.add(formBuildControl.id());
}
set.add(formBuildControl.id());
if (formBuildControl.isContainer())
printControls(formBuildControl);
}
}
;
printControls(this.design());
return flyingSet.pack();
}
Вывод в инфолог летающих контролов:
X++:
void upc_flyingControlsPrint()
{
Set set;
SetIterator si;
FormControl formControl;
;
set = Set::create(this.upc_flyingControlNumSet());
si = new SetIterator(set);
while(si.more())
{
formControl = editFormRun.control(si.value());
info(strfmt('%1 %2', formControl.id(), formControl.name()) );
si.next();
}
}
Пересоздание контролов (скрытие сущетсвующего и добавление нового):
X++:
void upc_flyingControlsRecreate()
{
Set set;
SetIterator si;
FormTreeItem formTreeItem;
Object control;
int cnt;
;
set = Set::create(this.upc_flyingControlNumSet());
si = new SetIterator(set);
while(si.more())
{
control = this.formControl(si.value());
formTreeItem = formControlTree.getItem(this.formControlTreeControl2Idx(si.value()));
this.upc_formControlTreeUserAdd(
control,
formControlTree.getParent(formTreeItem.idx()),
formTreeItem.idx() );
control.userHide(true);
cnt++;
si.next();
}
info(strfmt('Обработано полей: %1.', cnt));
}
Добавление контрола на основе существующего:
X++:
public FormControl upc_formControlTreeUserAdd(
Object _control,
TreeItemIdx _parentItemIdx,
TreeItemIdx _insertAfterItemIdx = 0 )
{
Object newControl,
insertAfterControl;
Object parentControl;
TreeNodeName treeNodeName;
int i;
;
if (formControlTree.getItem(_parentItemIdx))
{
parentControl = this.formControlTreeIdx2Control(_parentItemIdx);
if (parentControl &&
!parentControl.isContainer())
{
_insertAfterItemIdx = _parentItemIdx;
_parentItemIdx = formControlTree.getParent(_insertAfterItemIdx);
parentControl = this.formControlTreeIdx2Control(_parentItemIdx);
}
}
if (!parentControl)
{
parentControl = this.design();
}
if (parentControl)
{
parentControl.useUserLayout(true);
if (_insertAfterItemIdx)
{
insertAfterControl = this.formControlTreeIdx2Control(_insertAfterItemIdx);
}
if( this.formControlIsDataBound(_control) &&
_control.dataSource() )
{
if(_control.dataField())
{
newControl = parentControl.addDataField(
_control.dataSource(),
_control.dataField(),
insertAfterControl);
}
else if(_control.dataMethod())
{
i = 0;
do
{
i++;
treeNodeName = strfmt('%1_%2_%3', curuserid(), i, _control.dataMethod());
}
while(this.formControlIsNameUsed(treeNodeName));
newControl = parentControl.addControl(
SysFormRun::controlType(classidget(_control)),
treeNodeName,
insertAfterControl);
newControl.dataSource(_control.dataSource());
newControl.dataMethod(_control.dataMethod());
newControl.label(_control.label());
newControl.helpText(_control.helpText());
}
}
if (newControl)
{
newControl.markAsUserAdd(true);
this.formControlTreeAddControl(
newControl,
_parentItemIdx,
_insertAfterItemIdx,
true);
}
}
return newControl;
}
Ветка с датаметодом есть, но она не тестировалась мной.