20.07.2009, 16:03 | #1 |
Участник
|
Итератор с поддержкой методов обратного вызова для обработки контролов на форме
Для изменения свойств контролов на форме есть два подхода: либо править свойства в дизайне формы, либо делать это откуда-то из кода. Первый способ вроде бы наиболее простой, но он, порой, связан со значительными трудозатратами, кроме того, таким образом нельзя править свойства контролов, входящих в группы со свойством AutoDataGroup == Yes. При этом отказываться от этого чудесного свойства тоже не хотелось бы, поскольку оно позволяет за счет простого изменения группы полей на таблице менять перечень и порядок полей в группах на всех связанных формах.
С другой стороны, чтобы менять свойства контролов из кода, нужно обращаться к ним по одному, при этом контролы обычно должны иметь свойство AutoDeclaration == Yes, а для этого у группы, в которую входят контролы, необходимо обязательно выставить AutoDataGroup == No. Как вариант, можно в коде реализовать цикл обхода всех дочерних контролов той же группы, смотреть, к какому типу относится тот или иной дочерний контрол (потому что у наследников FormControl ряд свойств отличается, а в самом FormControl кое-какие свойства просто не реализованы, поэтому необходмо приведение типов дочерних контролов), тогда для группы можно оставить свойство AutoDataGroup == Yes. Но каждый раз организовывать такой цикл очень нудно: на одной и той же форме контролы в разных группах может понадобиться обрабатывать совершенно по-разному. Например, есть группы, в которые выведены коды пользователей либо сотрудников, а также display-методы для отображения их имен из таблицы сотрудников (EmplTable), плюс дата и время создания/модификации записи. Вот как это "штатно" выглядит: Видно, что для кодов пользователей и сотрудников (userId/emplId) значения свойств displayLength у расширенных типов отличаются, а для имен и значений времени тут совершенно излишни метки. Хотелось бы, чтобы эти группы выглядели примерно так: Так вот (та-да!) теперь этого можно легко добиться за счет использования итератора и методов обратного вызова, которые собственно будут устанавливать свойства контролов. В коде на форме это выглядит примерно так: X++: Set setOfIds; ; setOfIds = DEV_FormHelpers::addStringCtrlId2Set(); // на контролах какого типа должен дергаться метод обратного вызова DEV_iterateThroughFormControls( GrpAuthorNames, null, staticmethodstr(DEV_FormHelpers, hideLabel), setOfIds, true, classnum(DEV_FormHelpers) ); DEV_iterateThroughFormControls( GrpAuthorIds, null, staticmethodstr(DEV_FormHelpers, setColumnWidth), setOfIds, true, classnum(DEV_FormHelpers) ); setOfIds = DEV_FormHelpers::addTimeCtrlId2Set(); DEV_iterateThroughFormControls( GrpCreatedModifiedTime, null, staticmethodstr(DEV_FormHelpers, hideLabel), setOfIds, true, classnum(DEV_FormHelpers) ); Может возникнуть резонный вопрос, почему все-таки не изменить дизайн формы вручную раз и навсегда. Что ж, мне лично зачастую приходится создавать схожие по внешнему виду формы, отличающиеся некоторыми параметрами поведения и обрабатываемыми данными. Разумеется, лепить кучу форм-клонов неохота - куда интересней сделать одну форму и семейсво классов, управляющих ее поведением. Так вот, для изменения внешнего вида формы в зависимости от класса, который ей управляет, и понадобился такой механизм. Метод-итератор для рекурсивного перебора контролов на форме использует интерфейс DEV_IFormContainerControl, представляющий общие методы контролов-контейнеров (FormButtonGroupControl, FormGridControl, FormGroupControl, FormMenuButtonControl, FormTabControl, FormTabPageControl и - с одной оговоркой - FormDesign). Также в проект включены и другие вспомогательные интерфейсы - DEV_IFormButtonControl (общие методы и свойства FormButtonControl, FormCommandButtonControl и FormFunctionButtonControl) и DEV_IFormGridContainedControl (общие методы и свойства контролов, которые могут появиться на гриде при использовании табличных групп полей). Единственное неудобство использования этих интерфейсов - это необходимость при присваивании "интерфейсным" переменным ссылок на наследники FormControl использовать промежуточное приведение к Object. Впрочем, избавление от необходимости приведения того же FormControl к нужному типу его наследника, чтобы дернуть какой-нибудь метод, не определенный на FormControl, и унификация работы со схожими типами контролов, на мой взгляд, с лихвой компенсирует это неудобство. PS. Все это проверялось на AX3 |
|
|
За это сообщение автора поблагодарили: mazzy (2), sukhanchik (6), Logger (15), Ar (1), konopello (3), Jorj (1), Stainless (1), Kabardian (6). |
Теги |
design, form, formreferencegroupcontrol, дизайн, законченный пример, итератор, округление, полезное, форма |
|
|