| 
			
			 | 
		#1 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
			
			
			Как узнать, что форма открыта через "Перейти к форме основной таблицы"?
			 
			
			ax2009 и другие классические аксапты. 
		
		
		
		
		
		
			
		
		
		
		
	я в методе init добавил вызов метода, который правит query И вызывает executeQuery сама форма работает хорошо. но кнопка "Перейти к форме основной таблицы" не позиционируется на нужную запись, а показывает все записи нового запроса. Как узнать, что форма открыта через "Перейти к форме основной таблицы"?  | 
| 
	
 | 
| 
			
			 | 
		#2 | 
| 
			
			 NavAx 
		
			
	 | 
	
	
	
		
		
		
		 
			
			element.args().caller()?
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: mazzy (2). | |
| 
			
			 | 
		#3 | 
| 
			
			 Administrator 
		
			
	 | 
	
	
	
		
		
		
		 
			
			В общем случае никак. Ведь метод jumpRef перекрыть может каждый разработчик и написать там абсолютно любой код, в т.ч. вызвать форму без указания caller и прочих атрибутов. 
		
		
		
		
		
		
			Но если говорить про ядро, то есть же методы args,caller(), args.record(), args.lookupField(), args.lookupValue() - которые содержат осмысленные значения. Еще появился метод args.lookupRecord(). Соответственно, можно проанализировать эти методы на наличие заполненных значений и на основе этого сделать вывод о том, что форма была вызвана ядром через "Переход к основной таблице". 
				__________________ 
		
		
		
		
	Возможно сделать все. Вопрос времени  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: mazzy (2). | |
| 
			
			 | 
		#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). | |
| 
			
			 | 
		#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  | 
| 
	
 | 
| 
			
			 | 
		#6 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			Мне он тоже не очень нравится, но если ничего лучше не придумают, то думаю что можно. Опять же можно закладываться не на весь стек вызовов, а, например, поискать в глубину на 2-4 метода, есть ли в стеке метод с именем JumpRef и все. Тогда наследник SysSetupFormRun не повлияет.
		 
		
		
		
		
		
		
		
	 | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: mazzy (2). | |
| 
			
			 | 
		#7 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			может быть, тогда стоит переформулировать вопрос: 
		
		
		
		
		
		
			
		
		
		
		
	я должен модифицировать запрос на форме - включить/выключить childDatasource с existJoin, изменить Range в зависимости от переключателя на форме, который переключает пользователь (вот хотят они. причем обосновано) как лучше это сделать так, чтобы не сломать остальную функциональность аксапты?  | 
| 
	
 | 
| 
			
			 | 
		#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.  | 
| 
	
 | 
| 
			
			 | 
		#9 | 
| 
			
			 Боец 
		
			
	 | 
	
	
	
		
		
		
		 X++: public void init() { super(); info(strFmt("%1 %2 %3", element.args().lookupTable(), element.args().lookupField(), element.args().lookupValue())); }  | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: mazzy (2). | |
| 
			
			 | 
		#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). | |
| 
			
			 | 
		#11 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			А смена типа соединения отрабатывает? Вроде бы раньше не работало. 
		
		
		
		
		
		
		
	Имею ввиду вот это: X++: qbds.joinMode(JoinMode::InnerJoin); X++: SysQuery::findOrCreateDataSource(...) А вот последующие вызовы, когда ужа работает часть Find насколько помню, не работали - на существующем датасорсе не удавалось сменить тип связи.  | 
| 
	
 | 
| 
			
			 | 
		#12 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
а вот как оно там внутре... надо посмотреть.  | 
| 
	
 | 
| 
			
			 | 
		#13 | 
| 
			
			 Участник 
		
			
	 | 
	
	|
| 
	
 | 
|
| За это сообщение автора поблагодарили: mazzy (2). | |
| 
			
			 | 
		#14 | 
| 
			
			 Мрачный тип 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
К томе же реализация фильтров через queryRun().query() - не самый лучший вариант. Кто мешает пользователю в такой форме поиграться с запросом и вызвать стандартными средствами executeQuery(), похоронив все созданное непосильным трудом в queryRun().query() ? 
				__________________ 
		
		
		
		
		
			Мы летаем, кружимся, нагоняем ужасы ... Последний раз редактировалось TasmanianDevil; 10.03.2021 в 11:15.  | 
| 
	
 | 
| 
			
			 | 
		#15 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 Цитата: 
	
Цитата: 
	
если пользователь "сломает" мои фильтры, то метод get вернет MdmViewMode::UserDefined ![]() для моего кода это вполне штатная ситуация. Именно с queryRun! Это самый лучший вариант. Последний раз редактировалось mazzy; 10.03.2021 в 11:25.  | 
| 
	
 | 
| 
			
			 | 
		#16 | 
| 
			
			 Участник 
		
			
	 | 
	
	
	
		
		
		
		 
			
			args.refField()
		 
		
		
		
		
		
		
			
		
		
		
		
	 | 
| 
	
 | 
|
| За это сообщение автора поблагодарили: sukhanchik (3), Logger (3), Ace of Database (3), -DocSerzh- (1). | |