AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
DAX
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск Все разделы прочитаны

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 20.07.2009, 16:03   #1  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Итератор с поддержкой методов обратного вызова для обработки контролов на форме
Для изменения свойств контролов на форме есть два подхода: либо править свойства в дизайне формы, либо делать это откуда-то из кода. Первый способ вроде бы наиболее простой, но он, порой, связан со значительными трудозатратами, кроме того, таким образом нельзя править свойства контролов, входящих в группы со свойством 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_iterateThroughFormControls() - собственно метод-итератор, GrpAuthorNames и GrpAuthorIds - соотв. группы контролов со свойством AutoDeclaration == Yes, а DEV_FormHelpers - вспомогательный класс, чьи статические методы используются для выполнения действий над контролами. В принципе, ничто не мешает передавать в метод-итератор вместо null указатель на экземпляр какого-либо класса и название экземплярного метода этого класса, вместо того чтобы использовать статические методы DEV_FormHelpers.
Может возникнуть резонный вопрос, почему все-таки не изменить дизайн формы вручную раз и навсегда. Что ж, мне лично зачастую приходится создавать схожие по внешнему виду формы, отличающиеся некоторыми параметрами поведения и обрабатываемыми данными. Разумеется, лепить кучу форм-клонов неохота - куда интересней сделать одну форму и семейсво классов, управляющих ее поведением. Так вот, для изменения внешнего вида формы в зависимости от класса, который ей управляет, и понадобился такой механизм.
Метод-итератор для рекурсивного перебора контролов на форме использует интерфейс DEV_IFormContainerControl, представляющий общие методы контролов-контейнеров (FormButtonGroupControl, FormGridControl, FormGroupControl, FormMenuButtonControl, FormTabControl, FormTabPageControl и - с одной оговоркой - FormDesign). Также в проект включены и другие вспомогательные интерфейсы - DEV_IFormButtonControl (общие методы и свойства FormButtonControl, FormCommandButtonControl и FormFunctionButtonControl) и DEV_IFormGridContainedControl (общие методы и свойства контролов, которые могут появиться на гриде при использовании табличных групп полей). Единственное неудобство использования этих интерфейсов - это необходимость при присваивании "интерфейсным" переменным ссылок на наследники FormControl использовать промежуточное приведение к Object. Впрочем, избавление от необходимости приведения того же FormControl к нужному типу его наследника, чтобы дернуть какой-нибудь метод, не определенный на FormControl, и унификация работы со схожими типами контролов, на мой взгляд, с лихвой компенсирует это неудобство.

PS. Все это проверялось на AX3
Вложения
Тип файла: rar DEV_FormControlIterator.rar (4.7 Кб, 99 просмотров)
За это сообщение автора поблагодарили: sukhanchik (6), Stainless (1), konopello (3), Jorj (1), mazzy (2), Kabardian (6), Logger (15), Ar (1).
Старый 20.07.2009, 18:22   #2  
petr is offline
petr
Участник
Соотечественники
 
557 / 199 (8) ++++++
Регистрация: 30.05.2005
Адрес: Швейцария
Цитата:
Сообщение от gl00mie Посмотреть сообщение
С другой стороны, чтобы менять свойства контролов из кода, нужно обращаться к ним по одному, при этом контролы обычно должны иметь свойство AutoDeclaration == Yes, а для этого у группы, в которую входят контролы, необходимо обязательно выставить AutoDataGroup == No.
Непонял, что означает "обычно должны".

Вообще-то не должны. Для того, чтобы обатиться к контролу, у которого св-во AutoDeclaration установлено в No (например он входит в группу, и его св-ва недоступны) есть 2 способа.

1-ый. Работатет не для всех св-в, но не может породить run-time ошибки
FormDataSource.object(fieldId).visible(), enabled(), и некоторые другие.

2-ый. Предоставляет доступ ко всем св-вам, но может породить ошибку run-time
formStringControl = element.control(control::"имя контрола на форме");
За это сообщение автора поблагодарили: MerkurievV (0).
Старый 20.07.2009, 19:20   #3  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от petr Посмотреть сообщение
Для того, чтобы обатиться к контролу, у которого св-во AutoDeclaration установлено в No (например он входит в группу, и его св-ва недоступны) есть 2 способа.
1-ый. Работатет не для всех св-в, но не может породить run-time ошибки
FormDataSource.object(fieldId).visible(), enabled(), и некоторые другие.
Не, тут на выходе получается не FormControl, а FormDataObject, что не одно и то же. Для того, что может FormDataObject, разумеется, никакие ковыряния в контролах не нужны и, более того, вредны с идеологической точки зрения. Если нужно управлять поведением поля datasource'а на форме, это и надо делать через datasource - тут кто бы спорил.
Цитата:
Сообщение от petr Посмотреть сообщение
2-ый. Предоставляет доступ ко всем св-вам, но может породить ошибку run-time
formStringControl = element.control(control::"имя контрола на форме");
Именно этот способ я имел в виду, говоря «обычно должны иметь свойство AutoDeclaration == Yes». Но мне лично не нравится идея зашивать в код то, что нельзя проверить на этапе компиляции; на мой взгляд, использование enum'а Control на формах оправдано разве что в случае необходимости подправить дизайн формы через FormBuild-классы, т.е. до вызова super() в init() формы. Опять же, последний способ вынуждает обрабатывать контролы по одному, что мне лично не очень нравится.
За это сообщение автора поблагодарили: MerkurievV (0).
Старый 28.09.2009, 18:23   #4  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
В ряде случаев из-за кое-каких недотестированных доработок потребовалась возможность оперативно выяснять на формах, какие «на самом деле» суммы содержатся в отображаемых полях типа real. К примеру, забыли где-нить в импорте сумму округлять перед записью в поле таблицы, а потом - пойди, разберись, почему что-то не работает, ведь FormRealControl по умолчанию показывает значения с точностью лишь до двух знаков. Так вот, коллега на базе выложенного итератора реализовал возможность увидеть вещественные значения с большей точностью, приделав кнопку «Увеличить точность» к форме пользовательской настройки (SysSetupForm). На кнопке дергается такой код:
X++:
void clicked()
{
    super();
    infolog.startLengthyOperation();
    DEV_iterateThroughFormControls( sysSetupForm.getFormRun().design(),
                                    element,                        // объект, чей метод обратного вызова будет задействован
                                    @"DEV_setRealEditPrecision",    // название метода обратного вызова на форме SysSetupForm
                                    DEV_FormHelpers::addRealCtrlId2Set()
                                  );
    infolog.endLengthyOperation();
    element.close();                // показалось удобнее сразу закрывать форму настроек
}
В свою очередь, DEV_setRealEditPrecision() - это метод на форме SysSetupForm такого содержания:
X++:
// устанавливает для контролов RealEdit точность отображения минимум 6 знаков
#define.NewNoOfDecimals (6)
public void DEV_setRealEditPrecision(FormRealControl _formControl)
{
    if (!(  _formControl.noOfDecimalsMode() == AutoMode::Fixed
        &&  _formControl.noOfDecimalsValue() > #NewNoOfDecimals
       ))
    {
        _formControl.noOfDecimals( #NewNoOfDecimals, AutoMode::Fixed );
    }
}
Таким образом, за счет минимума кода стало можно на любой форме увидеть суммы/количества с большей точностью:

За это сообщение автора поблагодарили: Logger (9), sgt.Pepper (1).
Старый 28.09.2009, 22:55   #5  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,254 / 2155 (78) +++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от gl00mie Посмотреть сообщение
...на мой взгляд, использование enum'а Control на формах оправдано разве что в случае необходимости подправить дизайн формы через FormBuild-классы, т.е. до вызова super() в init() формы...
с этого места поподробней пожалуйста...
т.е. возможны случаи когда мы работаем через енум Control, но не можем использовать AutoDeclaration ?
Старый 29.09.2009, 11:30   #6  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Дело в том, что свойство AutoDeclaration, насколько я могу судить, действует на FormXXControl'ы, но не на FormBuildXXControl'ы. Более того, если попытаться даже присвоить переменной типа FormBuildXXControl ссылку на элемент управления с AutoDeclaration == Yes, то такой код просто не скомпилируется по причине несовместимости типов. Соответственно, если требуется на форме до вызова super() в init() получить ссылку на какой-либо FormBuildXXControl, скажем, чтобы передать ее параметром в класс, то тут AutoDeclaration никак не поможет.
Вот пример из моего скромного опыта: есть «многофункциональная» форма, работающая на базе строк журналов. Многофункциональность заключается в том, что в зависимости от параметров вызова эта форма должна показывать немного различающиеся наборы полей и реализовывать немного различающуюся логику. Для этого ею рулит семейство классов, каждый из которых (наследник от базового) реализует эти незначительные отличия. И вот встает задача: в зависимости от параметров вызова, кроме прочего, показывать на гриде формы разные наборы полей, причем для простоты каждый набор задан группой полей на соотв. таблице. Варианты были такие:
  • сделать на гриде кучу скрытых групп - по одной на нужную группу полей, а соответствующий класс будет делать видимой "свою" группу; но тут, выходит, надо ссылки на все эти группы передавать в класс, управляющий формой, либо реализовывать какую-то логику на форме (это хотелось делать в последнюю очередь, потому что исходно форма в плане логики "голая" - она только передает в класс ссылки на свои элементы и для некоторых событий дергает его обработчики);
  • сделать на гриде одну группу полей и менять из класса ее свойство DataGroup после инициализации формы - этот вариант показал свою полную несостоятельность;
  • сдалать на гриде одну группу полей и менять из класса ее свойство DataGroup до инициализации формы через ссылку на соотв. FormBuildGroupControl - на этом варианте я остановился.
Но тут встал вопрос: откуда добыть на форме ссылку на соотв. FormBuildGroupControl до инициализации формы, чтобы передать эту ссылку в класс? Я это сделал так:
X++:
element.form().design().control( Control::GrpGridFields );
тут, как видно, используется упомянутый enum Control, но AutoDeclaration задействовать в этом случае не представляется возможным.
Старый 29.09.2009, 12:17   #7  
Wamr is offline
Wamr
----------------
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
 
1,729 / 845 (32) +++++++
Регистрация: 15.01.2002
Адрес: Москва
Записей в блоге: 7
простите за вопрос.
На Dimension-полях работает?
Старый 29.09.2009, 13:13   #8  
Logger is offline
Logger
Участник
Лучший по профессии 2015
Лучший по профессии 2014
 
3,254 / 2155 (78) +++++++++
Регистрация: 12.10.2004
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от Wamr Посмотреть сообщение
простите за вопрос.
На Dimension-полях работает?
Мы проверяли - работает.
Старый 02.10.2009, 10:56   #9  
sgt.Pepper is offline
sgt.Pepper
Участник
Аватар для sgt.Pepper
 
43 / 15 (1) ++
Регистрация: 05.10.2007
Адрес: Германия
Небольшое исправление к коду для 4.0:

DEV_FormHelpers
X++:
private static Set getSetOfClassIds(Set _set)
{
    classId     locClassId;
    Set         ret;
    ;
    if (_set)
    {
        if (_set.typeId() != typeof(locClassId))
        {
            //callStack2Infolog();
            // for 4.0
            info(con2str( xSession::xppCallStack() ));
            throw error( error::wrongUseOfFunction( funcname() ) );
        }
        ret = _set;
    }
    else
    {
        ret = new Set( typeof(locClassId) );
    }
    return ret;
}
Старый 14.09.2010, 11:04   #10  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Во вложении - вспомогательный класс для итератора, обновленный для использования в AX 2009.

PS. Для себя я сделал класс DEV_FormHelpers используемым в итераторе по умолчанию в тех случаях, когда в качестве метода обратного вызова указывается статический, а не экземплярный метод (т.е. _callbackObject == null):
X++:
public static client boolean DEV_iterateThroughFormControls(
    Object          _parentControl,
    Object          _callbackObject,
    identifiername  _callbackObjectMethodName,
    Set             _setOfClassIds2InvokeOn,
    boolean         _recursive                      = true,
    classId         _staticCallbackMethodClassId    = classnum(DEV_FormHelpers)
   )
Вложения
Тип файла: zip DEV_FormHelpers-AX2009.zip (2.2 Кб, 53 просмотров)

Последний раз редактировалось gl00mie; 14.09.2010 в 11:40. Причина: typo...
Старый 15.09.2010, 08:33   #11  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,018 / 3935 (190) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
вопрос из другой ветки Как глобально отключить автоопределение ширины столбца = autoSizeColumns(false) ?

Цитата:
Сообщение от gl00mie Посмотреть сообщение
Оно бы хорошо, если б речь шла об однократном привешивании картонки к фанерной стене, однако ж, если верить перекрестным ссылкам, я лично этот итератор уже использовал в 16-и различных местах приложения.
а для каких задач может использоваться данный итератор?
__________________
GitHub, Facebook, mazzy.priot, mazzy.music, coub.
Старый 15.09.2010, 10:55   #12  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от mazzy Посмотреть сообщение
а для каких задач может использоваться данный итератор?
Собственно, большинство решаемых задач описаны в этой ветке:
  • какие-то универсальные вещи, наподобие кнопки "увеличить точность отображения" в настройке форм (SysSetupForm) или уже обсуждавшаяся рихтовка свойств grid'ов различных форм;
  • мелкая рихтовка вида контролов, которые входят в группы с AutoDataGroup = Yes (очень уж мне нравится это свойство, неохота от него отказываться из-за ерунды);
  • более затейливые сценарии, когда, к примеру, "нужно сделать форму, доступную только на чтение", при том что у потенциального пользователя есть доступ к ключам контроля доступа с уровнем выше, чем чтение - в этом случае при запуске формы с определенным параметром помимо установки свойств datasource'ов еще можно пробежаться по всем кнопкам и те, у которых NeededAccessLevel больше View (т.е. действия которых могут изменять данные на форме), - скрыть. Можно возразить, что надо такие вещи решать настройками прав доступа, но, пардон, UAC в виндах решает примерно те же задачи: хочешь - работай под администратором, имея полные права на все, но по умолчанию в действиях будешь ограничен. Конечно, такой подход требует корректного выставления NeededAccessLevel на пунктах меню, но при "традиционной" настройке прав доступа это требование не менее актуально.
  • сценарии, когда одна форма каких-нить журналов используется для ндцати (в моем случае - 10-и) немного отличающихся типов журналов, при этом одни и те же поля журналов для тех или иных типов могут иметь несколько отличающийся смысл, и пользователи хотят видеть там разные метки. В этом случае классы-наследники базового класса управления формой могут переопределить метод, возвращающий "нестандартную" метку для того или иного поля в строках журнала, а базовый класс дергает итератор, проходится по всем контролам, связанным с datasource'ом строк журнала, вызывает этот метод, возвращающий новую метку и, если возвращенное значение метки для поля, к которому привязан контрол, не пустое, устанавливает для контрола новую метку.
В общем, я лично с помощью итератора решаю в основном те задачи, которые при "традиционном" подходе требовали бы работы с каждым из заранее известного множества контролов в каждой из заранее известного множества форм, при том что эти множества на момент разработки могут быть еще неизвестны. "Традиционный" подход в таких случаях требует, как правило, слишком большого объема ручной работы, отказа от использования "автогрупп" контролов на основе табличных групп полей, внесения избыточных модификаций в стандартные формы (как с теми же гридами в AX 2009), плюс ко всему он еще и удорожает сопровождение сделанных модификаций.
Старый 15.09.2010, 11:29   #13  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,018 / 3935 (190) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от gl00mie Посмотреть сообщение
[/LIST]В общем, я лично с помощью итератора решаю в основном те задачи, которые при "традиционном" подходе требовали бы работы с каждым из заранее известного множества контролов в каждой из заранее известного множества форм, при том что эти множества на момент разработки могут быть еще неизвестны. "Традиционный" подход в таких случаях требует, как правило, слишком большого объема ручной работы, отказа от использования "автогрупп" контролов на основе табличных групп полей, внесения избыточных модификаций в стандартные формы (как с теми же гридами в AX 2009), плюс ко всему он еще и удорожает сопровождение сделанных модификаций.
Но ведь при таком подходе SysSetupForm превращается в бутылочное горлышко, которое "знает" о деталях других форм. Т.е. в SysSetupForm будет некий большой switch, которые знает о деталях поведения других форм.

Это же противоречит объектно-ориентированному подходу и полностью нарушает инкапсюляцию.
Говоря в терминологии C++, ты создаешь класс, который является френдом очень многих других классов. Эдакий супер-френд. Со всеми вытекающими последствиями, которые вроде обсуждались у программистов С++. Например, чтобы выявить особенности поведения, тебе недостаточно понять как работает сам объект и его класс, тебе нужно понять как работают и все френды.

Разве не так?
__________________
GitHub, Facebook, mazzy.priot, mazzy.music, coub.
Старый 15.09.2010, 12:38   #14  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Цитата:
Сообщение от mazzy Посмотреть сообщение
Но ведь при таком подходе SysSetupForm превращается в бутылочное горлышко, которое "знает" о деталях других форм. Т.е. в SysSetupForm будет некий большой switch, которые знает о деталях поведения других форм.
А откуда взялось мнение, что всё вышеописанное реализуется в SysSetupForm? Там реализована только кнопка увеличения точности отображения, которая может быть применена к любой форме. Если же мне нужно переделать свойства пары контролов на форме, и я не хочу их для этого выдергивать из "автогруппы", то я просто дописываю метод на самой этой форме либо в классе управления этой формой, который при ее инициализации с помощью итератора меняет эти свойства. Пример такого метода приведен в самом первом сообщении данной темы (и в комментарии к нему ясно написано: "В коде на форме это выглядит примерно так").

PS. Сперва очень долго не мог понять, при чем тут вообще SysSetupForm - мне и в голову не могло прийти совать в него код, специфичный для особенностей дизайна какой-то одной конкретной формы.

Последний раз редактировалось gl00mie; 15.09.2010 в 12:42.
Старый 15.09.2010, 13:42   #15  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
382 / 614 (21) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Цитата:
Сообщение от gl00mie Посмотреть сообщение
А откуда взялось мнение, что всё вышеописанное реализуется в SysSetupForm? Там реализована только кнопка увеличения точности отображения, которая может быть применена к любой форме. Если же мне нужно переделать свойства пары контролов на форме, и я не хочу их для этого выдергивать из "автогруппы", то я просто дописываю метод на самой этой форме либо в классе управления этой формой, который при ее инициализации с помощью итератора меняет эти свойства.
Для всяких хитровывернутых фич вещь, в принципе, полезная.

Но пара контролов на форме это пушкой по воробьям. Чем element.design().controlName() то не угодил? Вроде прекрасно достает контролы из автогрупп. Или уже не достает и я отстал от жизни?
За это сообщение автора поблагодарили: mazzy (2).
Старый 16.09.2010, 09:37   #16  
mazzy is offline
mazzy
Administrator
Аватар для mazzy
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
29,018 / 3935 (190) ++++++++++
Регистрация: 29.11.2001
Адрес: Москва
Записей в блоге: 10
Цитата:
Сообщение от gl00mie Посмотреть сообщение
А откуда взялось мнение, что всё вышеописанное реализуется в SysSetupForm?
А вот ни капельки такого мнения не было.
Реализуется метод в форме.
Но вызов то идет из SysSetupForm.
Это и есть friend.

Т.е. либо метод надо делать публичным, либо френдить SysSetupForm.
Поэтому SysSetupForm получается френдом для очень многих форм (другими словами, SysSetupForm слишком много знает о деталях реализации других форм), что приводит к снижению инкапсюляции.

(пусть в Аксапте нет ключевого слова friend. но смысл то и проблемы не меняются)

Цитата:
Если определяется класс, который не реализует математических объектов вроде матриц или комплексных чисел и не является типом низкого уровня наподобие связанного списка, то:
[а] Не используйте глобальных данных.
[b] Не используйте глобальных функций (не членов).
[c] Не используйте общих данных-членов.
[d] Не используйте функции friend (но только для того, чтобы избежать [а], [b] или [c]).
[e] Не обращайтесь к данным-членам другого объекта непосредственно.
[f] Не заводите в классе "поле типа"; используйте виртуальные функции.
[g] Используйте функции-подстановки только как средство значительной оптимизации.

...
Отметим, что общие базовые классы и друзья (friend) являются частью общего интерфейса класса (см. $$5.4.1 и $$12.4).
(C) Бьерн Страуструп. Язык программирования С++
__________________
GitHub, Facebook, mazzy.priot, mazzy.music, coub.

Последний раз редактировалось mazzy; 16.09.2010 в 10:04. Причина: добавил цитаты из Страуструпа
Старый 16.09.2010, 14:39   #17  
db is offline
db
Роман Долгополов (RDOL)
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
 
382 / 614 (21) +++++++
Регистрация: 01.04.2004
Адрес: Москва
Цитата:
Сообщение от mazzy Посмотреть сообщение
А вот ни капельки такого мнения не было.
Реализуется метод в форме.
Но вызов то идет из SysSetupForm.
Это и есть friend.
Да нет там никаких таких вызовов (Функционал "расширения сознания" не в счет - он на своем месте). Все остальные специфичные для отдельных форм вещи реализуются прямо на этих отдельных формах
За это сообщение автора поблагодарили: tricky (1).
Старый 14.03.2011, 21:15   #18  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,597 / 5258 (183) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 2
Поддержка FormBuild-контролов и опционального параметра для метода обратного вызова
Понадобилось тут подпилить один кусок кода в стандартном приложении, в связи с чем в итератор и вспомогательный класс DEV_FormHelpers была добавлена поддержка FormBuild-контролов и опционального параметра, который может передаваться в вызываемый из итератора метод обратного вызова. Через этот параметр можно организовать общение метода с вызывающим итератор кодом без заведения глобальных переменных. Во вложении - обновленный метод Global (итератор), вспомогательный класс и вспомогательные интерфейсы, которые раньше были выложены отдельно.

PS. Теперь DEV_FormHelpers является классом по умолчанию, чьи статические методы обратного вызова используются, если не задана ссылка на объект, реализующий метод обратного вызова, соотв., не обязательно указывать идентификатор этого вспомогательного класса в вызове итератора.
Вложения
Тип файла: zip DEV_FormControlIterator-AX2009.zip (7.1 Кб, 60 просмотров)

Последний раз редактировалось gl00mie; 14.03.2011 в 21:17.
За это сообщение автора поблагодарили: mazzy (2), Logger (2), wojzeh (1).
Старый 06.08.2013, 22:16   #19  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
611 / 403 (15) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
работает эта штука и в AX 2012! только что применил к FormReferenceGroupControl

спасибо!
__________________
Felix nihil admirari
Теги
design, form, formreferencegroupcontrol, дизайн, законченный пример, итератор, округление, полезное, форма

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
Проблема с передачей контролов из формы в класс matew DAX: Программирование 0 28.04.2008 17:37
Динамическое создание контролов на форме Yari DAX: Функционал 8 23.08.2007 13:51
Набор однотипных lookup() методов на форме johny77 DAX: Программирование 1 10.04.2007 13:12
Порядок отображения контролов на форме matew DAX: Программирование 1 26.10.2006 09:12
Русская локализация Axapta 3 ? SlavaK DAX: Администрирование 59 01.07.2003 22:38
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 18:10.
Powered by vBulletin® v3.8.5. Перевод: zCarot
Контактная информация, Реклама.