Книга знаний

1С:Предприятие / v8 / Приемы программирования / Формы

v8: Метод обработки событий изменения формы

Альтернативная схема построения обработчика событий формы.Автор статьи: Гений 1С | Редакторы:
Последняя редакция №5 от 21.04.06 | История
URL: http://kb.mista.ru/article.php?id=127

Ключевые слова: события,форма,схема


Исторически сложилось так, что обработка изменения данных, связанных с реквизитами формы обрабатывалась в обработчиках событий этих реквизитов. Так было в 77, так до сих пор пишется код типовых конфигураций. Однако в 80 появился метод ПодключитьОбработчикИзмененияДанных, с помощью которого код изменений можно писать более прозрачно.

Рассмотрим простейший пример: пусть у документа есть реквизиты "Валюта","Курс","Кратность","Контрагент","Договор","Дата".

При изменении реквизита "Валюта" нужно установить курс и кратность валюты на дату "Дата".
При изменении реквизита "Контрагент" нужно установить в реквизит "Договор" основной договор контрагента.

Классическая схема написания обработчиков событий формы будет такая:
Процедура Реквизит_Валюта_ПриИзменении()
  Курс=ПолучитьКурсПоВалюте(Валюта);
  Кратность=ПолучитьКратностьПоВалюте(Валюта);
КонецПроцедуры
Процедура Реквизит_Контрагент_ПриИзменении()
  Договор=ПолучитьОсновнойДоговорПоКонтрагенту(Контрагент);
КонецПроцедуры


Однако у приведенной схемы есть недостаток.
Допустим, пользователь создал новый документ и в него подставился контрагент по умолчанию.
По идее мы должны смоделировать в этой ситуации интерактивный выбор контрагента, чтобы проставился договор или скопировать код процедуры Реквизит_Контрагент_ПриИзменении.
Это можно сделать так:
[1с]
Выполнить(""+ПолучитьДействие(ЭлементыФормы.Контрагент,"ПриИзменении")+"(ЭлементыФормы.Контрагент)");
[/1с]
Или так:
[1с]
Реквизит_Контрагент_ПриИзменении();
[/1с]

Но хочется большей универсальности чтобы не приходилось дублировать код.
Добиться этого можно другой схемой:

[1с]
Процедура ПриОткрытии()
   …
       
   //Назначаем всем данным формы обработчик ИзменениеДанных
   Для Каждого Эл из ЭлементыФормы Цикл
       Попытка
           ПодключитьОбработчикИзмененияДанных(Эл.Данные, "ИзменениеДанных");
       Исключение
       КонецПопытки;
   КонецЦикла;

   ИзменениеДанных("*");

   …
   
КонецПроцедуры

Процедура ОтображениеДанных(Реквизит)
   Если Реквизит="Договор" ИЛИ Реквизит="Контрагент" ИЛИ Реквизит="*" Тогда
       ЭлементыФормы.кнВзаиморасчеты.Доступность=Пусто(Договор) Или Пусто(Контрагент);
   КонецЕсли;
КонецПроцедуры

Процедура ИзменениеДанных(Реквизит)
   Если Реквизит="Контрагент" Тогда
       Договор=ПолучитьОсновнойДоговорПоКонтрагенту(Контрагент);
   ИначеЕсли Реквизит="Валюта" Тогда
       Курс=ПолучитьКурсПоВалюте(Валюта);
       Кратность=ПолучитьКратностьПоВалюте(Валюта);
   КонецЕсли;
   ОтображениеДанных(Реквизит);
КонецПроцедуры
[/1с]

Конечно, было бы идеально, если подобные цепочки событий можно было описывать в модуле объекта, аналогично Delpy с их Property Get, Property Set (события по установке/чтению свойств объекта) но пока еще это не реализовано в 80.

А зачем нужен вызов с реквизитом "*"?
Этот вызов происходит при открытии формы и предназначен для правильного отображения статуса объектов.
Например, по задаче требуется, чтобы если был выбран договор и контрагент, то была доступна кнопка "кнВзаиморасчеты". Понятно, что контролировать доступность (отображение) этой кнопки нужно только при открытии формы и при изменении контрагента или договора. При открытии формы вызывается изменение данных всей формы (Реквизит "*"), в остальных случаях вызывается изменение каждого конкретного реквизита.

Кстати, заметим. В начале договор и контрагент пусты.
Пользователь вызывает договор. Пользователь вводит контрагента, вызывается событие ИзменениеДанных("Контрагент"), после чего проставляется договор и вызывается событие ИзменениеДанных("Договор"), после этого вызывается ОтображениеДанных("Договор"), которое делает кнопку "кнВзаиморасчеты" доступной и еще раз ОтображениеДанных("Контрагент"), которое оставляет кнопку доступной.

Как видно, при такой схеме обработки событий можно очень экономно писать код по обновлению отображения формы в зависимости от данных объекта, сравните с кодом, который вы обычно пишите в ОбновленииОтображения и почуствуйте разницу.


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

Архив обсуждений:
v8: Как отловить добавление строки в табличную часть в форме?








Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика