Форма AuthorEdit в Visual FoxPro
« Назад При нажатии в форме "Авторы" на кнопку "Новый" или "Изменить" открывается форма AuthorEdit (рис. 2.19), в которой можно задать значения полей новой записи или изменить существующую запись таблицы Authors. Рис. 2.19. Форма для ввода или редактирования записи В форму добавлены 2 свойства и 1 метод (рис. 2.20). Рис. 2.20. Новые свойства и метод формы Свойство NoError будет иметь значение .T., если при записи не возникнет ошибки. Свойство Op хранит значение параметра, передаваемого форме при ее открытии и равного либо 'new', если форма открыта для ввода новой записи, либо 'edit', если – для редактирования. Значение свойства Op определяется в обработчике события Init формы и далее не изменяется. Потребность в этом свойстве обусловлена тем, что область видимости параметра oPr формы – локальная, а его значение используется в других процедурах формы. Форма открывается модально (это видно из обработчика события Init формы) – переход в другое окно, пока форма открыта, невозможен. && Обработчик события Init формы AuthorEdit && lparameters oPr && Предотвращаем вывод сообщений команды CALCULATE set talk off This.WindowType = 1 && Открываем форму модально This.AutoCenter = .T. && и располагаем ее по центру экрана if not Used('Authors') then MessageBox("Таблица Authors должна быть открыта!") This.Command1.Enabled = .F. && Кнопка "Сохранить" будет недоступна This.Caption = "Таблица Authors не открыта" return endif select Authors if Pcount( ) = 0 then oPr = 'new' endif with This .Op = oPr && Op – новое свойство формы if oPr = 'new' then && Новая запись .Caption = 'Новая запись' && Заголовок формы recOld = Recno( ) && Ищем код нового автора calculate Max(AuthorId) to .AuthorId.Value go recOld AuthorId.Value = .AuthorId.Value + 1 && Инициализация значений свойства Value полей формы store "" to .Author.Value, .Information.Value .InputDate.Value = Date( ) && Текущая дата else && Редактирование записи .Caption = 'Редактирование записи' && Данные для полей формы берутся из таблицы Authors AuthorId.Value = AuthorId Author.Value = Author InputDate.Value = InputDate Information.Value = Information endif endWith Если форма открывается автономно, то число переданных параметров равно нулю. В этом случае в oPr устанавливается значение 'new'. Возможность автономного открытия формы предусмотрена для ускорения этапа ее проектирования. В случае новой записи (oPr = 'new') автоматически определяется код автора (используется команда CALCULATE), значение свойства Value поля ввода InputDate устанавливается равным текущей дате. В дальнейшем и код, и дата могут быть пользователем изменены. При редактировании в форме отображаются значения текущей записи таблицы Authors. После нажатия на кнопку "Сохранить", если возникнет ошибка, будет выполнен обработчик ее события Error: && Обработчик события Error кнопки "Сохранить" && lparameters nError, cMethod, nLine do case case nError = 1583 MessageBox("Нарушено правило проверки записи таблицы Authors!", 48) case nError = 1884 MessageBox("Код неуникален!", 48) otherwise MessageBox("Ошибка № " + Transform(nError) + " в строке " ; + Transform(nLine) + " метода " + cMethod, 32) endcase ThisForm.NoError = .F. Ошибка с номером 1583 возникает, когда нарушается заданное для таблицы Authors правило AuthorId >= 0 (см. рис. 2.12). Кроме того, поскольку индекс AuthorId является первичным, VFP самостоятельно проверить его уникальность. Если она нарушена, то возникнет ошибка с номером 1884. При любой обнаруженной ошибке обработчик события Error выдаст соответствующее предупреждение и свойство формы NoError получит значение .F., которое затем будет использовано обработчиком события Click кнопки "Сохранить". && Обработчик события Click кнопки "Сохранить" && local isDone isDone = .T. with ThisForm NoError = .T. if .CheckFields( ) then begin transaction && Начинаем транзакцию іf .Op = 'new' then insert into Authors ; values(.AuthorId.Value, ; Author.Value, ; InputDate.Value, ; Information.Value) else if IsRlocked( ) or not Rlock( ) MessageBox("Запись недоступна!") isDone = .F. else replace AuthorId with .AuthorId.Value, ; Author with .Author.Value, ; InputDate with .InputDate.Value ; Information with .Information.Value endif record Recno && Снимаем блокировку записи endif if isDone and .NoError then end transaction && Завершаем транзакцию Release && Освобождаем форму else && Отмена изменений при обнаружении ошибки rollBack endif endif endWith Обработчик обеспечивает либо добавление записи в таблицу Authors, либо замену текущей. Однако эти операции будут выполнены, если, во-первых, данные не содержат пустых значений и, во-вторых, не возникло ошибки исполнения и, следовательно, не был вызван обработчик события Error кнопки "Сохранить". Отвечает за проверку полей добавленный в форму метод CheckFields: && Метод CheckFields формы AuthorEdit && with ThisForm && && Проверяем поля ввода; они не должны быть пустыми if Empty(.AuthorId.Value) then MessageBox('Задайте код!') return .F. endif if Empty(.Author.Value) then MessageBox('Не задан автор!') return .F. endif if Empty(.InputDate.Value) then MessageBox('Нужно задать дату ввода данных об авторе!') return .F. endif endWith Замечание. Если бы система не выполняла проверку уникальности кода автора автоматически, то в рассматриваемый метод пришлось бы добавить следующий код: with ThisForm && && Проверка уникальности кода recOld = Recno( ) ordOld = Order( ) set order to AuthorId flag = .T. if Seek(.AuthorId.Value) then if .Op = 'new' then && Новая запись MessageBox('Код не уникален!') flag = .F. else && Редактирование записи do while .AuthorId.Value = AuthorId and not Eof( ) if Recno( ) != recOld then MessageBox('Код не уникален!') flag = .F. exit endif skip enddo endif endif go recOld set order to (ordOld) return flag endWith В приведенном варианте доступа к таблицам Authors и BooksAuthors буферизация не используется; таблица BooksAuthors задействуется при выполнении триггера __RI_UPDATE_authors( ). Форма закроется, если данные записаны (транзакция завершена). В этом случае isDone и ThisForm.NoError имеют значение .T. Значение isDone определяется обработчиком события Click кнопки "Сохранить": если запись заблокирована текущим приложением или если не удается заблокировать запись, то переменная isDone получит значение .F. и команда REPLACE выполнена не будет. Если же нажать на "Отказ", то выполнится метод ThisForm.Release и форма закроется. В принципе, в обработчик события Click кнопки "Отказ" можно встроить вопрос, например такой: "Закрыть форму?", и при отрицательном ответе работа с формой должна быть продолжена. |