|  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. | 
|  |