В процессе разработки в среде 1С:Предприятие часто возникает задача синхронизации состояния нескольких открытых форм. Типичный пример: из основного документа создается подчиненный, и после его записи в основной форме должны отобразиться изменения (например, статус заполнения или новые строки). Рассмотрим детально, как реализовать автоматическое обновление форм, и проанализируем, какие архитектурные подходы считаются наиболее правильными.
Самый распространенный и технически простой способ — использование глобального механизма оповещений. Этот метод позволяет одной форме «подать сигнал», а всем остальным открытым формам — «услышать» его и среагировать. Разберем реализацию по шагам.
Шаг 1. Отправка оповещения из подчиненного документа
В форме документа, который вносит изменения (в нашем случае это «Журнал входного контроля» (поможет система автоматизации входного контроля для 1С)), Консоль кода с ИИ-помощником ускорит написание обработчиков, необходимо прописать код в обработчике ПослеЗаписи. Мы используем процедуру Оповестить, которая рассылает сообщение всем открытым окнам текущего сеанса.
&НаКлиенте
Процедура ПослеЗаписи(ПараметрыЗаписи)
// Оповещаем систему, что связанные данные изменились
// Первый параметр - имя события (произвольная строка)
// Второй параметр - структура с данными (ссылка на документ-основание)
ПараметрыОповещения = Новый Структура("ДокументОснование", Объект.ДокументОснование);
Оповестить("ОбновлениеЖВК", ПараметрыОповещения, ЭтаФорма);
КонецПроцедуры
Шаг 2. Прием оповещения в основной форме
В форме документа, который нужно обновить (например, «Поступление товаров розницы»), создаем обработчик события ОбработкаОповещения — для этого подойдёт набор инструментов разработчика 1С с ИИ-помощником. Выясним причину использования именно этого метода: он позволяет выполнить перечитывание данных из базы без закрытия формы.
&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
// Проверяем, наше ли это событие и относится ли оно к текущему документу
Если ИмяСобытия = "ОбновлениеЖВК" И Параметр.ДокументОснование = Объект.Ссылка Тогда
// Важный нюанс: перед чтением проверяем, не редактировал ли пользователь форму
Если ЭтаФорма.Модифицированность Тогда
// Если форма изменена, просто перечитывать нельзя - данные пользователя затрутся.
// Можно либо предупредить пользователя, либо пропустить обновление.
Возврат;
КонецЕсли;
// Читаем актуальные данные из базы данных в объект формы
ЭтаФорма.Прочитать();
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию, описанную в обсуждении: стоит ли вообще менять данные в основном документе при записи подчиненного? Analyzer 1C поможет выявить все связи объекта. Профессиональное сообщество склоняется к тому, что это плохая практика. Рассмотрим причины:
Решение: Вместо хранения признака Заполнен непосредственно в реквизитах документа, используем Регистр сведений. Использование ресурсов регистров сведений обеспечит надежное хронологическое хранение. В него будем записывать информацию о связи документов. На форме основного документа эту информацию можно выводить через запрос или динамический список.
Если нам нужно просто визуально отобразить статус в табличной части, можно обойтись без хранения данных. Программное перемещение колонки позволит гибко настроить вид списка. Разберем, как сделать колонку «полностью динамической»:
Вместо использования стандартной табличной части Объект.Товары, мы можем разместить на форме Динамический список с произвольным запросом. В этом запросе мы левым соединением подтянем данные из ЖВК.
Преимущество этого метода: автоматическое обновление. При использовании метода ОповеститьОбИзменении(Ссылка) платформа сама обновит все динамические списки, где фигурирует эта ссылка, без написания дополнительного кода в ОбработкаОповещения.
Иногда возникают ситуации, когда прямая связь между формами затруднена (например, формы открыты в разных контекстах или это старая конфигурация). В таких случаях можно использовать «костыль» в виде обработчика ожидания.
&НаКлиенте
Процедура ПриОткрытии(Отказ)
// Подключаем проверку раз в 30 секунд
ПодключитьОбработчикОжидания("ПроверитьОбновленияДокумента", 30, Ложь);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьОбновленияДокумента()
// Здесь можно выполнить легкий серверный вызов для проверки версии объекта
// Если версия изменилась - вызываем ЭтаФорма.Прочитать()
КонецПроцедуры
Важное предостережение: Метод с обработчиком ожидания создает лишнюю нагрузку на сервер и сеть. Используйте его только тогда, когда другие способы (оповещения, динамические списки) не применимы.
Разберем важные детали, которые часто упускают разработчики:
1. Свойство Модифицированность: Как уже упоминалось, вызов ЭтаФорма.Прочитать() полностью заменяет данные в памяти формы данными из БД. Если ваш пользователь в этот момент вводил количество или цену, его труд будет потерян. Всегда проверяйте ЭтаФорма.Модифицированность или используйте частичное обновление через серверные вызовы без перечитывания всего объекта. Для этой задачи есть конструктор поведения форм и контроля ввода без программирования.
2. Оптимистическая блокировка: Если данные в базе изменились, а форма не была обновлена, при попытке записи пользователь получит ошибку: «Данные были изменены или удалены другим пользователем». Программное обновление через Прочитать() — это единственный способ актуализировать версию данных в памяти формы и избежать этой ошибки.
3. Web-клиент: Помните, что в браузере механизмы оповещения могут работать с задержкой. Также частое обновление форм в веб-интерфейсе может приводить к визуальному «мерцанию» страницы.
4. Система взаимодействия: Если вам нужно обновить форму у другого пользователя (в другом сеансе), стандартный метод Оповестить не сработает. Для этого в современных версиях платформы используется СистемаВзаимодействия, позволяющая пересылать сообщения между сеансами через сервер.
Для решения задачи программного обновления формы наиболее эффективным является сочетание Метода 1 (Оповещение) для оперативного отклика интерфейса и Метода 2 (Регистры сведений) для корректной архитектуры данных. По возможности старайтесь уходить от хранения служебных статусов внутри первичных документов, заменяя их динамическим считыванием данных через запросы.