28.02.2012, 19:14 | #1 |
Участник
|
Добавление полей на форму в run-time
В init() формы CustTable после super() пишу следующий код (добавляю группу полей)...
X++: void init() { FormTabControl fcContainer; FormGroupControl fcGroup; //FormBuildTabPageControl fcContainer; //FormBuildGroupControl fcGroup; ; //... some code before super() ... super(); fcContainer = element.design().controlName('TabGeneral'); // fcContainer = element.form().design().control('TabGeneral'); fcGroup = fcContainer.addControl(FormControlType::Group, 'Vendor2'); fcGroup.dataSource(tableStr(CustTable)); fcGroup.dataGroup('Vendor'); // fcGroup.autoDataGroup(true); Что я делаю не так? UPD. Если вместо дизайна element.design() использовать element.form().design(), см. закомментированные части кроме последней строки, Акса падает. UPD 2. Попробовал добавить группу полей в run() до и после super()... результат - тот же. Неужели поля из группы добавлять вручную? |
|
|
За это сообщение автора поблагодарили: A-Lis-A (1). |
28.02.2012, 19:48 | #2 |
Участник
|
В принципе неправильно.
добавление - операция, требующая тщательного программирования и переписывания кучи параметров. поступайте наоборот - скрывайте ненужные поля. всего одной строчкой на каждое поле. в форме предусмотрите все возможные поля, а в коде - скрывайте. |
|
28.02.2012, 20:01 | #3 |
Участник
|
Цитата:
Для меня важно НИКАК не модифицировать форму. На самом деле, код выше - тестовый, ибо настоящий код, модифицирующий формы, вызывается в наследниках класса FormRunListener_W. Меня устроит только добавление элементов. И, повторюсь, НИКАКИХ изменений форм! Я взываю к людям, которые мне подскажут, как Вы правильно заметили, как всё тщательно запрограммировать... мне важен принцип, а не код. UPD. Я могу написать код, который будет добавлять все поля из группы полей таблицы, но неужели это единственный путь?! Вот и интересно, что я делаю не так (при моём подходе ) Последний раз редактировалось Ar; 28.02.2012 в 20:04. |
|
28.02.2012, 23:21 | #4 |
Участник
|
Использовать element.design() надо после super() в init() формы - в этом случае работа будет идти с об'ектами времени выполнения (FormDesign, FormXXControl); до super() они еще просто не инициализированы. Использовать element.form().design() надо до super() в init() - в этом случае работа будет идти с об'ектами времени дизайна (FormBuildDesign, FormBuildXXControl). Добавить группу контролов, основанную на табличной группе полей, из моего скромного опыта, можно только контролами времени дизайна, при этом не обязательно выставлять AutoDataGroup = true у FormBuildGroupControl, все поля и так появятся; более того, ядро трешки стабильно падало, если выставлять у добавляемой на лету группы AutoDataGroup = true, в 2009-й это поправили.
|
|
|
За это сообщение автора поблагодарили: Ar (1), A-Lis-A (1). |
29.02.2012, 00:57 | #5 |
Участник
|
Цитата:
Сообщение от gl00mie
Использовать element.design() надо после super() в init() формы - в этом случае работа будет идти с об'ектами времени выполнения (FormDesign, FormXXControl); до super() они еще просто не инициализированы. Использовать element.form().design() надо до super() в init() - в этом случае работа будет идти с об'ектами времени дизайна (FormBuildDesign, FormBuildXXControl). Добавить группу контролов, основанную на табличной группе полей, из моего скромного опыта, можно только контролами времени дизайна
Я уже успел разобраться про ДО и ПОСЛЕ super() в init(). Теперь я добавляю группу полей ДО super(). Поля в группу успешно добавляются, однако, только для существующего DataSource. Добавить новый DataSource пока не получилось Т.е. осталось решить одну малость... ДО super() добавить источник данных, связанный с одним из уже существующих... |
|
29.02.2012, 01:13 | #6 |
Участник
|
в 2009 не получится, я уже пробовал,
если быть точнее - получится только для тех форм, на которых нет контролов с autodeclaration=yes AX резервирует область в памяти для контролов со свойсвом autodeclaration=yes сразу после указателей на DS. при добавлении нового DS мы можем получить ссылку на контролы, вместо DS вот собственно пример - если убрать автодекларейшн - всё работает (но с учетом вышесказанного - я бы не рискнул это использовать) В 2012 это исправили - за это можете мне плюсики поставить, за суппорт реквест вендору =) Последний раз редактировалось lvan; 29.02.2012 в 01:29. |
|
|
За это сообщение автора поблагодарили: AlGol (0), Ar (0), S.Kuskov (0), A-Lis-A (0). |
29.02.2012, 03:18 | #7 |
Участник
|
Цитата:
С удовольствием поставлю... через несколько дней... как убежусь, что невозможно создать датасорс вообще. |
|
29.02.2012, 07:49 | #8 |
Участник
|
В подтверждение слов Ivan пост от vallys в теме Динамическое создание DataSource на форме, и добавление элементов дизайна.
Цитата:
Сообщение от vallys
Как-то потребовалось создавать диалоги с источниками данных и гридами. В качестве альтернативы созданию собственных форм для каждого случая, была использована одна собственная диалоговая форма (можно модифицировать стандартную форму Dialog) с заранее созданными искуственными источниками данных, которые позднее переопредилялись в RunBase.dialog(...). Динамически создавать источники данных в стандартной форме не получилось по предпологаемой причине, описанной ниже. Далее имхо.
Представьте, что экземпляры объектов, таких как DataSource, DataSource_DS, DataSource_Q, DataSource_QR, и экземпляры контролов с AutoDeclaration = Yes, хранятся некоторым списком. Сами переменные, используемые в коде формы, имеют смысл ссылок на позицию (адрес) в этом списке. При чем экземпляры объектов для источников данных хранятся перед контролами. При добавлении нового источника данных у формы "создаются новые" экземпляры объектов, которые сдвигают контролы в списке. Естественно указатели на контролы становятся неверными, поэтому и возникают ошибки при обращении к ним. В вашем случае - при обращении к StaticText. Решение: либо добавить нужное количество источников данных на форму заранее в репозитарий, либо, если первое не возможно, как минимум отказаться от использования контролов с AutoDeclaration = Yes (данным путем не ходил, возможно потребуется ввести и другие ограничения) |
|
|
За это сообщение автора поблагодарили: Ar (1). |
29.02.2012, 21:35 | #9 |
Участник
|
Спасибо всем за участие.
В следствие того, что баг справлен в 2012, а мы туда обязательно придём, пока пошёл путём малой крови... и отошёл от условий - на форму добавляю новый DataSource, всё остальное получается сделать до super() в init(): X++: Object fcContainer; FormGroupControl fcGroup; int fDS; ; fDS = formRun.form().design().dataSource(_DSName); fcContainer = formRun.form().design().control(_containerName); fcGroup = fcContainer.addControl(FormControlType::Group, _groupName); fcGroup.dataSource(fDS); fcGroup.dataGroup(_tableGroupName); |
|
29.02.2012, 23:53 | #10 |
Участник
|
К слову сказать датасурс на форме не обязательно жёстко привязывать к конкретной таблице. При создании в свойствах в качестве таблицы можно указать Common, а в run-time уже заменить на реальное значение. Таким образом можно создав заранее некоторое количество "не типизированных" источников данных в run-time получить любую комбинацию таблиц. Связи между источниками данных естественно тоже можно настраивать в run-time.
|
|
01.03.2012, 01:22 | #11 |
Участник
|
ну так сделано в TableBrowser собственно
я туда первым делом полез смотреть, когда у меня эта задача возникла |
|
01.03.2012, 07:39 | #12 |
Участник
|
Тут есть "нюанс" с правами доступа: вроде как права доступа на таблицу datasource'а проверяются ядром до init(). При этом, с одной стороны, на Common висит ключ AdminTables, так что либо надо будет отключать AllowCheck на таком datasource'е, либо всем потенциальным пользователям как-то подкручивать права (не помню, видна ли Common в настройке прав доступа), иначе форма не откроется. А с другой стороны, после подмены таблицы в datasource'е права доступа на нее проверены ядром на открытии формы уже не будут.
|
|
|
За это сообщение автора поблагодарили: mazzy (2), lev (2), S.Kuskov (5). |
01.03.2012, 07:54 | #13 |
Участник
|
|
|
01.03.2012, 08:41 | #14 |
Участник
|
Как повторно запустить неявную проверку прав, выполняемую ядром, не знаю - я в таких случаях явно проверяю права доступа на таблицу таким вот методом вспомогательного класса DEV_Assert:
X++: // если у текущего пользователя нет доступа к указанной таблице, выбрасывает исключение public static client server void hasTableAccess(tableId _tableId, AccessType _accessType = AccessType::View) {; DEV_Assert::tableIdIsInValidRange(_tableId); if (!isTableUserEnabled(_tableId, _accessType)) { throw error(strfmt("@SYS76214", tableid2pname(_tableId))); } } |
|
01.03.2012, 09:41 | #15 |
Участник
|
Цитата:
права нужно проверять не только на таблицу, но и на отдельные поля. также нужно:
если всего этого не сделать, то получится отдельно стоящая форма, не связанная с остальным функционалом. И ни на что не похожая. В которой НЕ работают большинство стандартных и таких привычных пользователю инструментов. (Даже порядок колонок не запоминается!) повторюсь: |
|
01.03.2012, 10:27 | #16 |
Участник
|
Позволю сделать одно маленькое замечание: дополнительное программирование может потребоваться в случае, если дабавлять Common, в противном случае, дорабатывать не надо, всё и так работает.
Кстати, в большинстве случаев (для подобных модификаций) всего описанного Вами функционала не требуется. Но, согласен, разработчик должен знать, к чему ведёт такой подход... |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
01.03.2012, 11:28 | #17 |
Участник
|
а вы попробуйте
Цитата:
вот так всегда - сначала громкие заявления про "универсальность", а потом(!) выясняется... |
|
01.03.2012, 18:26 | #18 |
Участник
|
Собственно, я и писАл на форум именно после того, как попробовал.
В моём случае всё в порядке, т.е. все пункты Вашего списка работают так, как надо, ибо я свой источник (не Common) линковал к уже существующему. Разумеется, возможно найти пример, где некоторые или даже (о, ужас!) все пункты не будут работать... Думаю, искать и не требуется. Ну а что поделать?! К сожалению, мы вынуждены адаптироваться под условия... При наличии багов в 2009 и зная, что их исправили в 2012, можно и отступить на время... Вряд ли стОит тратить на задачу больше сил, чем это необходимо. |
|
|
За это сообщение автора поблагодарили: sukhanchik (2). |
01.03.2012, 19:39 | #19 |
Участник
|
Цитата:
не верю, выкладывайте проект. |
|
01.03.2012, 21:28 | #20 |
Участник
|
Да не вопрос! Сделал маленький тест... т.к. оригинальный проект выкладывать будет тяжко... много всего.
Не проверял только автоотчёт и выгрузку в XL. Всё остальное работает P.S. Перечисленные Вами глюки начинают происходить исключительно если на форму в run-time добавляем группы полей (возможно и просто поля? не пробовал) одного и того же DataSource, уже где-то присутствующие на форме... Акса начинает путаться и при загрузке форм меняет свойства первых попавшихся, а не тех, что нужно, полей. Что-то с run-time идентификаторами контролов. |
|
|
За это сообщение автора поблагодарили: mazzy (5). |
Теги |
autodatagroup, autodeclaration, datasource, run-time, добавление группы полей, как правильно, форма |
|
Опции темы | Поиск в этой теме |
Опции просмотра | |
|