09.03.2021, 11:31 | #1 |
Участник
|
Как узнать, что форма открыта через "Перейти к форме основной таблицы"?
ax2009 и другие классические аксапты.
я в методе init добавил вызов метода, который правит query И вызывает executeQuery сама форма работает хорошо. но кнопка "Перейти к форме основной таблицы" не позиционируется на нужную запись, а показывает все записи нового запроса. Как узнать, что форма открыта через "Перейти к форме основной таблицы"? |
|
09.03.2021, 11:50 | #2 |
NavAx
|
element.args().caller()?
|
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.03.2021, 12:00 | #3 |
Administrator
|
В общем случае никак. Ведь метод jumpRef перекрыть может каждый разработчик и написать там абсолютно любой код, в т.ч. вызвать форму без указания caller и прочих атрибутов.
Но если говорить про ядро, то есть же методы args,caller(), args.record(), args.lookupField(), args.lookupValue() - которые содержат осмысленные значения. Еще появился метод args.lookupRecord(). Соответственно, можно проанализировать эти методы на наличие заполненных значений и на основе этого сделать вывод о том, что форма была вызвана ядром через "Переход к основной таблице".
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.03.2021, 12:31 | #4 |
Участник
|
Можно еще посмотреть стек вызовов вызовом xSession::xppCallStack()
При обычном открытии там что-то типа (C)\Forms\MyForm\Methods\init (C)\Classes\SysSetupFormRun\init А если переход к основной таблице, то что-то типа такого (C)\Forms\MyForm\Methods\init (C)\Classes\SysSetupFormRun\init (C)\Classes\FormDataObject\jumpRef (C)\Classes\FormStringControl\jumpRef (C)\Classes\FormRun\Task (C)\Classes\SysSetupFormRun\Task (C)\Classes\FormStringControl\Context |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.03.2021, 12:39 | #5 |
Участник
|
а разве caller заполняется только для jumpRef?
хотя мысль хорошая, а не сломались ли и остальные случаи с заполненным caller. И что это за случаи. Спасибо. Продуктивная мысль. Цитата:
Сообщение от Logger
Можно еще посмотреть стек вызовов вызовом xSession::xppCallStack()
При обычном открытии там что-то типа (C)\Forms\MyForm\Methods\init (C)\Classes\SysSetupFormRun\init А если переход к основной таблице, то что-то типа такого (C)\Forms\MyForm\Methods\init (C)\Classes\SysSetupFormRun\init (C)\Classes\FormDataObject\jumpRef (C)\Classes\FormStringControl\jumpRef (C)\Classes\FormRun\Task (C)\Classes\SysSetupFormRun\Task (C)\Classes\FormStringControl\Context |
|
09.03.2021, 12:42 | #6 |
Участник
|
Мне он тоже не очень нравится, но если ничего лучше не придумают, то думаю что можно. Опять же можно закладываться не на весь стек вызовов, а, например, поискать в глубину на 2-4 метода, есть ли в стеке метод с именем JumpRef и все. Тогда наследник SysSetupFormRun не повлияет.
|
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.03.2021, 12:43 | #7 |
Участник
|
может быть, тогда стоит переформулировать вопрос:
я должен модифицировать запрос на форме - включить/выключить childDatasource с existJoin, изменить Range в зависимости от переключателя на форме, который переключает пользователь (вот хотят они. причем обосновано) как лучше это сделать так, чтобы не сломать остальную функциональность аксапты? |
|
09.03.2021, 13:22 | #8 |
Administrator
|
Цитата:
Вариант 1. Стандартная форма, нестандартный вызов. Например, вызываем форму InventTrans из своей формы, в которой есть строки с номенклатурами. В этом случае в своей форме в методе jumRef пишем что-то типа X++: Args args; Query query; QueryBuildDataSource qbds; ; query = new Query(); qbds = query.addDataSource(tableNum(InventTransOrigin)); qbds.addRange(fieldNum(InventTransOrigin, InventTransId)).value(queryValue(_inventTransId)); args = new Args(); args.initialQuery(InitialQueryParameter::createByQuery(query)); MenuFunction::runClient(menuitemDisplayStr(InventTrans), MenuItemType::Display, true, args); Для некоторых случаев есть уже готовые методы типа X++: InventJournalFormTable::jumpRefReferenceId(inventJournalTable.JournalId); Вариант 2. Стандартная / малоизмененная форма, свой вызов. Добавили новое поле в форму CustTable и хотим по нему сделать свой переход. Тогда есть 2 решения - либо как в Варианте 1, либо на init формы / датасорса уже открываемой формы анализировать методы класса Args: caller / lookupField / record / lookupValue, которые уж несложно заполнить из jumpRef-а вызываемой формы
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 09.03.2021 в 13:52. |
|
09.03.2021, 14:22 | #9 |
Боец
|
X++: public void init() { super(); info(strFmt("%1 %2 %3", element.args().lookupTable(), element.args().lookupField(), element.args().lookupValue())); } |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
09.03.2021, 14:39 | #10 |
Участник
|
element.args().caller() - хорошая мысль. но очень грубо
element.args().lookup*() - прекрасно. спасибо. но я пошел уже другим путем и отрефакторил. принцип по которому я пошел:
получился вот такой код: X++: protected static MdmViewMode get(FormDataSource fdsMain, TableId shadowTableId) { MdmViewMode ret; EnumId enumId = enumnum(MdmType); QueryRun qr = fdsMain ? fdsMain.queryRun() : null; QueryBuildDataSource qbds = qr ? qr.query().dataSourceTable(shadowTableId, 1) : null; SysDictField field = qbds ? SysDictTable::fieldWithEnum(qbds.table(), enumId) : null; QueryBuildRange qbr = field ? qbds.findRange(field.id()) : null; str rangeValue = qbr ? qbr.value() : ''; ; if( !qbds || !qbds.enabled() ) { ret = MdmViewMode::All; } else if( qbds && qbds.joinMode() == JoinMode::NoExistsJoin && rangeValue == SysQuery::value(MdmEnumViewMode::completed()) ) { ret = MdmViewMode::InProcess; } else if( qbds && qbds.joinMode() == JoinMode::NoExistsJoin && rangeValue == SysQuery::value(MdmType::StopProcessing) ) { ret = MdmViewMode::Active; } else if( qbds && qbds.joinMode() == JoinMode::ExistsJoin && rangeValue == SysQuery::value(MdmType::StopProcessing) ) { ret = MdmViewMode::Stopped; } else if( qbds && qbds.joinMode() == JoinMode::ExistsJoin && rangeValue == SysQuery::value(MdmType::Error) ) { ret = MdmViewMode::Error; } else { ret = MdmViewMode::UserDefined; } return ret; } X++: // предполагаем, что в запросе только один range по полю mdmType protected static boolean set( FormDataSource fdsMain, TableId shadowTableId, MdmViewMode viewMode) { EnumId enumId = enumnum(MdmType); QueryRun qr = fdsMain ? fdsMain.queryRun() : null; QueryBuildDataSource qbds = qr ? SysQuery::findOrCreateDataSource(qr.query(), shadowTableId, fdsMain.table()) : null; SysDictField field = qbds ? SysDictTable::fieldWithEnum(qbds.table(), enumId) : null; str rangeValue; ; if( qbds && field ) { startLengthyOperation(); switch( viewMode ) { case MdmViewMode::UserDefined: qbds.enabled(true); qbds.relations(true); qbds.joinMode(JoinMode::InnerJoin); rangeValue = SysQuery::valueUnlimited(); break; case MdmViewMode::All: qbds.enabled(false); qbds.relations(true); qbds.joinMode(JoinMode::ExistsJoin); rangeValue = SysQuery::valueUnlimited(); break; case MdmViewMode::InProcess: qbds.enabled(true); qbds.relations(true); qbds.joinMode(JoinMode::NoExistsJoin); rangeValue = SysQuery::value(MdmEnumViewMode::completed()); break; case MdmViewMode::Active: qbds.enabled(true); qbds.relations(true); qbds.joinMode(JoinMode::NoExistsJoin); rangeValue = SysQuery::value(MdmType::StopProcessing); break; case MdmViewMode::Stopped: qbds.enabled(true); qbds.relations(true); qbds.joinMode(JoinMode::ExistsJoin); rangeValue = SysQuery::value(MdmType::StopProcessing); break; case MdmViewMode::Error: qbds.enabled(true); qbds.relations(true); qbds.joinMode(JoinMode::ExistsJoin); rangeValue = SysQuery::value(MdmType::Error); break; default: throw error(Error::unsupportedEnum(funcname(), viewMode)); } qbds.fetchMode(QueryFetchMode::One2One); qbds.firstOnly(true); SysQuery::findOrCreateRange(qbds, field.id()).value(rangeValue); fdsMain.research(); endLengthyOperation(); return true; } return false; } до жамка: после жамка: спасибо за советы и помощь. |
|
|
За это сообщение автора поблагодарили: sukhanchik (2), Raven Melancholic (2). |
10.03.2021, 07:09 | #11 |
Участник
|
А смена типа соединения отрабатывает? Вроде бы раньше не работало.
Имею ввиду вот это: X++: qbds.joinMode(JoinMode::InnerJoin); X++: SysQuery::findOrCreateDataSource(...) А вот последующие вызовы, когда ужа работает часть Find насколько помню, не работали - на существующем датасорсе не удавалось сменить тип связи. |
|
10.03.2021, 07:41 | #12 |
Участник
|
Цитата:
а вот как оно там внутре... надо посмотреть. |
|
10.03.2021, 11:11 | #13 |
Участник
|
|
|
|
За это сообщение автора поблагодарили: mazzy (2). |
10.03.2021, 11:11 | #14 |
Мрачный тип
|
Цитата:
К томе же реализация фильтров через queryRun().query() - не самый лучший вариант. Кто мешает пользователю в такой форме поиграться с запросом и вызвать стандартными средствами executeQuery(), похоронив все созданное непосильным трудом в queryRun().query() ?
__________________
Мы летаем, кружимся, нагоняем ужасы ... Последний раз редактировалось TasmanianDevil; 10.03.2021 в 11:15. |
|
10.03.2021, 11:22 | #15 |
Участник
|
Цитата:
Цитата:
если пользователь "сломает" мои фильтры, то метод get вернет MdmViewMode::UserDefined для моего кода это вполне штатная ситуация. Именно с queryRun! Это самый лучший вариант. Последний раз редактировалось mazzy; 10.03.2021 в 11:25. |
|
13.09.2021, 10:16 | #16 |
Участник
|
args.refField()
|
|
|
За это сообщение автора поблагодарили: sukhanchik (3), Logger (3), Ace of Database (3), -DocSerzh- (1). |
Теги |
reffield |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|