v8: Метод обработки событий изменения формы Ключевые слова: события,форма,схема
Исторически сложилось так, что обработка изменения данных, связанных с реквизитами формы обрабатывалась в обработчиках событий этих реквизитов. Так было в 77, так до сих пор пишется код типовых конфигураций. Однако в 80 появился метод ПодключитьОбработчикИзмененияДанных, с помощью которого код изменений можно писать более прозрачно.
Рассмотрим простейший пример: пусть у документа есть реквизиты "Валюта","Курс","Кратность","Контрагент","Договор","Дата".
При изменении реквизита "Валюта" нужно установить курс и кратность валюты на дату "Дата".
При изменении реквизита "Контрагент" нужно установить в реквизит "Договор" основной договор контрагента.
Классическая схема написания обработчиков событий формы будет такая:
Процедура Реквизит_Валюта_ПриИзменении()
Курс=ПолучитьКурсПоВалюте(Валюта);
Кратность=ПолучитьКратностьПоВалюте(Валюта);
КонецПроцедуры
Процедура Реквизит_Контрагент_ПриИзменении()
Договор=ПолучитьОсновнойДоговорПоКонтрагенту(Контрагент);
КонецПроцедуры
Однако у приведенной схемы есть недостаток.
Допустим, пользователь создал новый документ и в него подставился контрагент по умолчанию.
По идее мы должны смоделировать в этой ситуации интерактивный выбор контрагента, чтобы проставился договор или скопировать код процедуры Реквизит_Контрагент_ПриИзменении.
Это можно сделать так:
[1с]
Выполнить(""+ПолучитьДействие(ЭлементыФормы.Контрагент,"ПриИзменении")+"(ЭлементыФормы.Контрагент)");
[/1с]
Или так:
[1с]
Реквизит_Контрагент_ПриИзменении();
[/1с]
Но хочется большей универсальности чтобы не приходилось дублировать код.
Добиться этого можно другой схемой:
[1с]
Процедура ПриОткрытии()
…
//Назначаем всем данным формы обработчик ИзменениеДанных
Для Каждого Эл из ЭлементыФормы Цикл
Попытка
ПодключитьОбработчикИзмененияДанных(Эл.Данные, "ИзменениеДанных");
Исключение
КонецПопытки;
КонецЦикла;
ИзменениеДанных("*");
…
КонецПроцедуры
Процедура ОтображениеДанных(Реквизит)
Если Реквизит="Договор" ИЛИ Реквизит="Контрагент" ИЛИ Реквизит="*" Тогда
ЭлементыФормы.кнВзаиморасчеты.Доступность=Пусто(Договор) Или Пусто(Контрагент);
КонецЕсли;
КонецПроцедуры
Процедура ИзменениеДанных(Реквизит)
Если Реквизит="Контрагент" Тогда
Договор=ПолучитьОсновнойДоговорПоКонтрагенту(Контрагент);
ИначеЕсли Реквизит="Валюта" Тогда
Курс=ПолучитьКурсПоВалюте(Валюта);
Кратность=ПолучитьКратностьПоВалюте(Валюта);
КонецЕсли;
ОтображениеДанных(Реквизит);
КонецПроцедуры
[/1с]
Конечно, было бы идеально, если подобные цепочки событий можно было описывать в модуле объекта, аналогично Delpy с их Property Get, Property Set (события по установке/чтению свойств объекта) но пока еще это не реализовано в 80.
А зачем нужен вызов с реквизитом "*"?
Этот вызов происходит при открытии формы и предназначен для правильного отображения статуса объектов.
Например, по задаче требуется, чтобы если был выбран договор и контрагент, то была доступна кнопка "кнВзаиморасчеты". Понятно, что контролировать доступность (отображение) этой кнопки нужно только при открытии формы и при изменении контрагента или договора. При открытии формы вызывается изменение данных всей формы (Реквизит "*"), в остальных случаях вызывается изменение каждого конкретного реквизита.
Кстати, заметим. В начале договор и контрагент пусты.
Пользователь вызывает договор. Пользователь вводит контрагента, вызывается событие ИзменениеДанных("Контрагент"), после чего проставляется договор и вызывается событие ИзменениеДанных("Договор"), после этого вызывается ОтображениеДанных("Договор"), которое делает кнопку "кнВзаиморасчеты" доступной и еще раз ОтображениеДанных("Контрагент"), которое оставляет кнопку доступной.
Как видно, при такой схеме обработки событий можно очень экономно писать код по обновлению отображения формы в зависимости от данных объекта, сравните с кодом, который вы обычно пишите в ОбновленииОтображения и почуствуйте разницу.
Однако в бочке меда есть ложка дегтя - все вышесказанное не работает для таблиц значения и табличных частей. Обработкик подключить можно, но он не вызывается при изменениях. Это очень печально и надеюсь, в будущих версиях платформы будет исправлено.
Архив обсуждений:
v8: Как отловить добавление строки в табличную часть в форме?
|