24.09.2008, 15:34 | #1 |
Участник
|
Как сохранить строку только при нажатии кнопки?
Как сделать так чтобы строка которая создана в гриде с Ctrl+N (и строки в других таблицах связанные с этой) , сохранялась толко если я назжимаю какуюто свою кнопку, даже если строка валидируется итд?
|
|
24.09.2008, 15:38 | #2 |
Боец
|
salesTable_ds.write()
P.S. Вам нужно пропустить валидацию строки или сохранить ? Если сохранить, то перед salesTable_ds.write() вызвать validateWrite() Последний раз редактировалось DSPIC; 24.09.2008 в 15:43. |
|
24.09.2008, 16:25 | #3 |
Ищущий знания...
|
наверное имеется ввиду что бы не сохранялось автоматически, а только если нажал кнопку. Если так то, необходимо на форму добавить параметр например isClickedButton типа boolean и далее в тех таблицах, которые вам необходимо сохранять только по нажатию кнопки, добавить условие перед super(). Например:
X++: void write(boolean _isClickedButton = false) { if(_isClickedButton) super(); } X++: void clicked() { SalesTable_ds.write(true); super(); }
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем Последний раз редактировалось lev; 24.09.2008 в 16:29. |
|
24.09.2008, 16:46 | #4 |
Участник
|
Lev : Спасибо за ответ. А такие подходы считаюстья нормальными или ето хак? А переопределяя методы можно добавлять параметры - не знал
А как сделать чтобы если нажать другую кнопку, то в гриде сосданная запись исчезает, или ето и будут последствия приведенного Вами кода? Последний раз редактировалось sweeper; 24.09.2008 в 16:58. |
|
24.09.2008, 17:03 | #5 |
Ищущий знания...
|
такой подход нормальный
что значит исчезает? удаляется?
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
24.09.2008, 17:50 | #6 |
Участник
|
Не получается Что я сделал - в датасорце таблицы добавил метод write, как Вы дали в примере. А записи все равно остаются
Вообще же моей задачей является сделать форму в которой есть грид, записи в который можно добавлять толко через другую (детальную) форму, в которой видно все поля однои записи. Если в етой деталной форме нажать Сохранить, то форма закрывается и в гриде появляется запись, если нажать Отменить, то форма закрывается без сохранения записи. Мне на етом форуме порекомендовали посмотреть пример SalesTable, но он настолько сложный что я не разобрался. |
|
24.09.2008, 17:54 | #7 |
Ищущий знания...
|
Так погодите, тот пример что я написал, это пример для сохранения строки по кнопке.
Что бы записи удалялись только по одной строке нужно перекрывать метод delete().
__________________
"Страх перед возможностью ошибки не должен отвращать нас от поисков истины." (с) С Уважением, Елизаров Артем |
|
24.09.2008, 20:17 | #8 |
Administrator
|
Цитата:
Сообщение от sweeper
Вообще же моей задачей является сделать форму в которой есть грид, записи в который можно добавлять толко через другую (детальную) форму, в которой видно все поля однои записи. Если в етой деталной форме нажать Сохранить, то форма закрывается и в гриде появляется запись, если нажать Отменить, то форма закрывается без сохранения записи.
Мне на етом форуме порекомендовали посмотреть пример SalesTable, но он настолько сложный что я не разобрался. Итак, открываем (в коде) форму SalesTable, как Вам порекомендовали. Для начала следует знать две вещи: 1. Best Practice рекомендует минимизировать код на форме. В стандарте это требование реализуется с помощью одного или нескольких классов, в которых размещается весь код, который "хочется" поместить на форме. Для каждого обработчика события на форме должен быть создан соответствующий метод этого "форменного" класса, который вызывается из метода формы и содержит всю обработку этого события. Это условие соблюдается однако далеко не везде - но тем не менее - при создании записи в форме SalesTable это используется. 2. Создание записи в форме вызывает метод create на датасорсе. И если не вызвать super - то создания записи не произойдет. Метод "форменного" класса - salesTableForm.create() - возвращает true, если нажата кнопка ОК в детальной форме и false - в противном случае. Поэтому в методе create формы SalesTable сделан if и super вызывается только если нажата кнопка ОК в детальной форме Теперь - о том - как в детальной форме сохранять или не сохранять запись. Кнопки в этой форме (SalesCreateOrder) сделаны типа CommandButton, с командой ОК или отмена. Эти команды примечательны тем, что: 1. Автоматически закрывают форму 2. При закрытии вызывают методы формы closeOk и closeCancel, а также устанавливают флажки (это тоже методы формы) closedOk и closedCancel, т.о. позволяя в коде понять - какая из кнопок нажата. Нажатие кнопки Esc эквивалентно выполнении команды Отмена, т.е. нажатию кнопки Отмена. Поскольку любое сохранение записи в форме вызывает метод write на датасорсе формы, то на детальной форме SalesCreateOrder в методе write стоит до вызова super() проверка: если не была нажата кнопка ОК (!closedOk) - то super() не вызывать и как следствие - запись не сохранять. Возвращаясь к форме SalesTable - хочу отметить, что (если из метода create на датасорсе SalesTable перейти в метод "форменного" класса SalesTableForm.create()) форма SalesCreateOrder вызывается во-первых из класса, что дает возможность передать в другую форму этот же экземпляр "форменного" класса, а во-вторых используется метод wait() у формы - что позволяет остановить исполнение кода до закрытия детальной формы SalesCreateOrder, после чего проверить - какая кнопка была нажата (if closedOk). Попутно - обращаю внимание - что непосредственное сохранение записи в таблице SalesTable происходит в методе write датасорса salesTable формы SalesCreateOrder. Там не вызывается super(), а вызывается непосредственно метод insert() на таблице (почему так сделано - это отдельный вопрос), а затем (смотрим код чуть ниже) новый SalesId сохраняется в "форменном" классе SalesCreateForm (метод newSalesId), который потом "достается" уже в методе create на датасорсе SalesTable формы SalesTable (смотрим строчку SalesTable::find) и курсор на датасорсе устанавливается на свежесозданную запись (строка salesTable.data(newSalesTable)) с последующей перечиткой этой записи датасорса (строка salesTable_ds.reread()). Перечитка нужна потому, что запись физически была создана из кода (метод write формы SalesCreateOrder) и параллельно с этим - виртуально (т.е. без записи в базу) - после вызова super() в методе create формы SalesTable. Перечитка позволяет датасорсу забыть про виртуальную запись и отображать запись из базы Вот.... Этот механизм хоть и сложный - но он показывает - как в Аксапте правильно делать тот механизм, который Вас попросили сделать. Сложность данного механизма (в частности, использование "форменного" класса) окупается легкостью обработки кнопок на форме и если форма многофункциональная - то только так и надо делать. Все остальное (использование методов create, write, closedOk, closedCancel) являются всего лишь средствами языка программирования Х++, которые могут и не иметь аналогов в других языках программирования. Вот такой механизм - задействован в форме SalesTable. Его весьма полезно будет осознать и претворять в жизнь дальше.
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 24.09.2008 в 20:30. |
|
25.09.2008, 00:26 | #9 |
Участник
|
Замечу, что для предотвращения навигации по SalesTable в форме SalesCreateOrder предприняты дополнительные шаги (точнее один шаг). У SalesTable установлено в false свойство AutoQuery.
Вследствие этого, при открытии формы на сервер не уходит запрос на выборку данных и в локальном кэше датасорса ничего нет, по-этому нажатие навигационных кнопок в панели инструментов ни к чему не приводит. Кроме кнопки перехода на последнюю запись, которая отправляет на сервер запрос, в результате чего форма начинает работать на редактирование уже существующих записей. По-моему, в данном случае необходимо перекрывать все навигационные методы на датасорсе (last(), first(), next(), prev(), prevPage(), nextPage()) и комментировать в них вызов super(). Думаю, вызов insert() вместо super() в методе write() датасорса этим и обусловлен. Если бы происходил вызов super(), то могла бы возникнуть ситуация сохранения изменений в уже существующие записи. При вызове insert() в этом случае запись не сохранится с сообщением об уже существующей
__________________
Axapta v.3.0 sp5 kr2 |
|
25.09.2008, 10:44 | #10 |
MCTS
|
Цитата:
Сообщение от AndyD
Замечу, что для предотвращения навигации по SalesTable в форме SalesCreateOrder предприняты дополнительные шаги (точнее один шаг). У SalesTable установлено в false свойство AutoQuery.
Вследствие этого, при открытии формы на сервер не уходит запрос на выборку данных и в локальном кэше датасорса ничего нет, по-этому нажатие навигационных кнопок в панели инструментов ни к чему не приводит. Кроме кнопки перехода на последнюю запись, которая отправляет на сервер запрос, в результате чего форма начинает работать на редактирование уже существующих записей. По-моему, в данном случае необходимо перекрывать все навигационные методы на датасорсе (last(), first(), next(), prev(), prevPage(), nextPage()) и комментировать в них вызов super(). |
|
25.09.2008, 11:02 | #11 |
Administrator
|
и эта идея не нова . Она применяется мастере (Wizard), который является мастером с данными (наследник SysDefaultDataWizard). Обработкой курсора временной таблицы занимается наследник класса SysDefaultData, который по указанию программиста "сливает" содержимое этой временной таблицы в такую же таблицу, но уже в БД.
Так что - есть решения - на любой вкус и цвет
__________________
Возможно сделать все. Вопрос времени |
|
25.09.2008, 11:15 | #12 |
Участник
|
Цитата:
И еще делать код по переносу из временной в постоянную таблицу
__________________
Axapta v.3.0 sp5 kr2 |
|
25.09.2008, 11:23 | #13 |
Участник
|
Цитата:
Правда, это слишком кропотливый способ и не гарантирует что все лазейки закроются. Например при закрытии формы по кресту - все равно будет стремиться сохранить запись. |
|
25.09.2008, 15:22 | #14 |
MCTS
|
Цитата:
Все-таки временная таблица, имхо, как-то по безопасней будет. Пока не нажал на красную кнопку - все действия во временном буфере, а как нажал - запись попала в базу. А то мало ли куда пользователь может нажать во время ввода данных... |
|
26.09.2008, 01:18 | #15 |
Участник
|
Всем спасибо за ответы! Особенно sukhanchik-у. Попробую употребить на практике. Совсем неожидал такого бурного отклика форумчан, спасибо
Вопрос sukhanchik-у. Для редактирования уже созданной записи тоже должна открыватся детальная форма (после того как активирована какаято запись и нажата кнопка Редактировать). Для етого ещё много надо доделывать? А способ с временными таблицами проще или нет? Меня как новичка в Ахапте ужасает что шаг налево, шаг на право и ничего не работает и потом понять где ошибка может только человек который уже успел в Ахапте натереть мозоли Последний раз редактировалось sweeper; 26.09.2008 в 01:42. |
|
26.09.2008, 12:15 | #16 |
Administrator
|
тут-то как раз все просто. Если в Вашей таблице есть ключевое поле с EDT, который смотрит на эту же таблицу (аналогично полю SalesId в таблице SalesTable с EDT SalesId) - то Вы просто делаете форму с тем же датасорсом. При переходе из одной формы в другую - у Вас просто свяжутся две записи по этому ID и ядро физически не позволит перейти на другую запись.
Проблема будет в другом. Аксапта в большинстве своих форм предполагает редактирование непосредственно на форме с автоматическим сохранением - так что если Вам вдруг придет в голову идея добавить кнопки Сохранить-Отмена - то гоните эту идею прочь . Хотя - вполне можно поступить также как в форме SalesCreateOrder - перекрыть метод write на датасорсе и потом анализировать методы closedOk/closedCancel Он другой. Его может объяснить тяжелее. Идея такова - делается форма с датасорсом. На методе init датасорса после super делается из датасорса временная табличка (MyTable_ds.cursor().setTmp()). Далее - все работает как обычно. Но в конце надо будет из этой временной таблички - все слить в постоянную табличку (объявляется новая переменная, потом копируются все поля из временной таблички и вызывается метод insert()). За кажущейся простотой - стоят особенности работы с временными таблицами в аксапте (нельзя терять курсор), возможное отсутствие возможности использовать существующий функционал (если он есть), и вообще сам факт использования временных таблиц. Одно дело - когда все работает стандартно с БД, другое дело - когда Аксапта должна сама создавать еще отдельный файл (пусть временный) - куда чего-то еще записывать. Плюс - если у вас при формировании записи выделяется номер из номерной серии - то для записи во временной табличке его либо не нужно выделять, либо рисковать потерей выделенного номера (если пользователь нажмет кнопку Отмена). Поэтому - если Вы новичок - то я бы Вам советовал бы сначала освоить первый способ. Потом - отдельно - познакомиться с особенностью работы с временными таблицами в Аксапте - а потом - сделать вывод - что проще. В любом случае - с т.з. оценки работы программиста - лучше - когда он пишет в стиле стандартного функционала и по максимуму использует возможности уже написанного кода или поведение ядра для минимизации кода. Нет смысла за Аксапту делать insert(), лучше уж заставить работать метод write на датасорсе - так как надо. Но и палку перегибать не надо. В разобранном мною примере - как раз insert() оправдан в рамках минимизации перекрытия кол-ва методов навигации (см сообщение от AndyD) Цитата:
Поэтому ряд методов в ядре слабо оттестирован, либо еще и незадокументирован - поэтому - гарантию работоспособности может дать только тот код, который уже работает в каком-то месте. Поэтому - самый лучший способ программирования в Аксапте - "посмотреть как работает там и сделать по аналогии".
__________________
Возможно сделать все. Вопрос времени Последний раз редактировалось sukhanchik; 26.09.2008 в 12:19. |
|