При разработке и сопровождении конфигураций часто возникает ситуация: на форме родительского объекта (например, справочника физических лиц) расположено поле ввода со ссылкой на подчиненный справочник (гражданство, документ, удостоверяющий личность, и т. д.). Пользователь открывает форму подчиненного элемента по кнопке открытия или по клавише F4, редактирует реквизиты, сохраняет объект и закрывает окно. Однако в форме владельца в поле ввода сохраняется старое текстовое представление до тех пор, пока вручную не будет нажата кнопка обновления или форма не будет переоткрыта.
Проанализируем причины такого поведения платформы 1С:Предприятие и разберем эффективные способы автоматического обновления отображения данных.
Чтобы правильно устранить проблему, выясним, как платформа обрабатывает действия пользователя:
ОбработкаВыбора у элемента управления вызывается только тогда, когда значение получено из формы списка или формы выбора через метод ОповеститьОВыборе(). При переходе в уже выбранный элемент через кнопку открытия (лупу) выбора не происходит — открывается форма редактирования объекта, поэтому обработчик ОбработкаВыбора не срабатывает.Обновить(): Вызов ЭтаФорма.Обновить() выполняет перерисовку элементов интерфейса, но не обращается повторно к базе данных для перечитывания кэшированных представлений ссылок.Рассмотрим решение, основанное на отправке оповещения при записи подчиненного объекта и переприсваивании реквизита в форме владельца для принудительного сброса кэша.
В модуле формы подчиненного справочника в обработчике события записи отправляем оповещение:
Процедура ПослеЗаписи(Отказ)
Оповестить("ОбновитьГражданство", ЭтотОбъект.Ссылка, ЭтотОбъект);
КонецПроцедуры
В форме владельца (например, справочника физических лиц) определяем процедуру обработки оповещения. Для сброса кэша представления и обновления текста в поле ввода присваиваем реквизиту его же собственное значение:
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ОбновитьГражданство" Тогда
Гражданство = Гражданство;
ИначеЕсли ИмяСобытия = "ОбновитьУдостоверение" Тогда
Удостоверение = Удостоверение;
КонецЕсли;
КонецПроцедуры
Важный момент: Конструкция Гражданство = Гражданство; инициирует событие изменения значения в элементе управления, заставляя платформу пересчитать строковое представление ссылки и вывести актуальное наименование.
ОповеститьОбИзмененииРазберем универсальный механизм платформы 1С:Предприятие. Глобальный метод ОповеститьОбИзменении() сообщает клиентскому приложению о том, что данные конкретного объекта изменились, и платформа автоматически обновляет представления и динамические списки во всех открытых формах.
В модуле формы подчиненного элемента в событии ПослеЗаписи вызываем следующий код:
Процедура ПослеЗаписи(Отказ)
ОповеститьОбИзменении(Ссылка);
КонецПроцедуры
При использовании этого метода нет необходимости вручную перехватывать оповещения в форме владельца и переприсваивать переменные — платформа выполнит сброс кэша представления ссылки автоматически.
Открытие элемента формыРассмотрим вариант, когда открытие формы подчиненного справочника полностью контролируется из формы владельца.
Для поля ввода назначаем обработчик события Открытие, отключаем стандартную обработку и открываем форму программно:
Процедура ГражданствоОткрытие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если ЗначениеЗаполнено(Гражданство) Тогда
ФормаПодчиненного = Гражданство.ПолучитьФорму();
ФормаПодчиненного.ОткрытьМодально();
// После закрытия модальной формы принудительно обновляем значение
Гражданство = Гражданство;
КонецЕсли;
КонецПроцедуры
Этот подход полезен, когда логика работы требует дождаться окончания редактирования подчиненного объекта перед продолжением работы в основной форме.
Посмотрим на ситуацию, когда в подчиненной форме создается новый объект, и его ссылку необходимо сразу вернуть в форму владельца. Для этого платформа предоставляет метод ОповеститьОЗаписиНовогоОбъекта().
В модуле подчиненной формы вызываем метод после создания объекта:
Процедура ПослеЗаписи(Отказ)
Если ЭтоНовый() Тогда
ОповеститьОЗаписиНовогоОбъекта(Ссылка);
КонецЕсли;
КонецПроцедуры
В форме владельца перехватываем стандартное событие ОбработкаЗаписиНовогоОбъекта:
Процедура ОбработкаЗаписиНовогоОбъекта(Объект)
Если ТипЗнч(Объект) = Тип("СправочникСсылка.Гражданство") Тогда
Гражданство = Объект;
КонецЕсли;
КонецПроцедуры
Таким образом, мы рассмотрели различные механизмы синхронизации данных между формами. Для типовых задач редактирования существующих данных наиболее лаконичным решением является метод ОповеститьОбИзменении() либо механизм Оповестить() с переприсваиванием реквизита в ОбработкаОповещения.