Встряну со своим "пятаком". Пришлось делать нечто подобное для поля диалога(!), где, как известно, ни датасорсов, ни релэйшенов. Использовал подход с controlMethodOverload. Поступил радикально - запер пользователя в контроле после ввода "плохого" значения методом leave, который срабатывает всегда:
X++:
public boolean MyDialogField1_leave()
{
boolean ret;
FormStringControl me = dialog.formRun().controlCallingMethod();
MyTable table;
;
ret = me.leave(); // как super
// далее наш функционал, который должен отрабатывать на событие
select table where table.Field1 == me.text();
// если указано непустое значение, отсутствующее в списке,
// то не выпускаем из поля
if (! table && me.text())
{
box::stop('Значение отсутствует в списке!');
ret = ret && false;
}
return ret;
}
Метод размещен в некотором классе, предназначенном для обработки событий именно этого конкретного диалога. Названия полей диалога по умолчанию вида "Fld1_1" динамически заменил на более содержательные: "MyDialogField1" - чтобы не переписывать заголовки методов в классе, если вдруг в дальнейшем придется добавить в диалог новые поля и имена по умолчанию "съедут" (Ax 3.0, SP4).
Ну, а в методе, формирующем собственно диалог, перед вызовом run расположился такой блок операторов:
X++:
dialog.doInit();
dialog.formRun().controlMethodOverload( true );
dialog.formRun().controlMethodOverloadObject( new MyEventHandlerForThisDialog( dialog ));
dialog.run();