Как обновить данные в первой форме после их изменения во второй форме в 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

Разработка интерактивных интерфейсов в системе «1С:Предприятие» часто требует организации взаимодействия между несколькими формами. Типичный сценарий: из основной (первой) формы пользователь открывает вспомогательную (вторую) форму, вносит в нее изменения (например, добавляет запись в регистр сведений или меняет реквизиты объекта), закрывает ее, и обновленные данные должны мгновенно отобразиться на первой форме.

В этой статье мы подробно разберем, как реализовать такое поведение. Мы рассмотрим классические подходы для обычных форм (актуально для систем на платформе 1С 8.2 и совместимых версий 8.3), а также разберем современные и наиболее надежные методы для управляемых форм.

Метод 1. Системное оповещение об изменении (Рекомендуемый способ для обычных форм)

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

Рассмотрим ситуацию, когда во второй форме мы записываем данные в регистр сведений. Сразу после успешной записи выполним следующий код во второй форме:


// Во второй форме после записи набора или менеджера записи регистра сведений
ОповеститьОбИзменении(Тип("РегистрСведенийКлючЗаписи.ИмяВашегоРегистра"));

Если во второй форме редактируется объект (например, элемент справочника или документ), в качестве параметра метода следует передать ссылку на этот объект:


// Оповещение об изменении конкретного элемента справочника
ОповеститьОбИзменении(СсылкаНаОбъект);

Как это работает: Платформа 1С самостоятельно находит все запущенные динамические списки и табличные поля, отображающие данные этого типа на первой форме, и инициирует их обновление. Программисту не требуется писать дополнительный код обновления в модуле первой формы — всё происходит автоматически силами платформы.

Метод 2. Явный вызов экспортного метода первой формы через Владельца

Если нам требуется не просто обновить стандартный список, а выполнить сложный алгоритм (например, пересчитать итоги, изменить видимость элементов или заполнить дерево значений), мы можем связать формы напрямую через механизм владельца формы.

Выясним, как реализовать этот подход по шагам:

  1. При открытии второй формы из первой обязательно передаем контекст первой формы в качестве параметра Владелец:

// Код в модуле первой формы для открытия второй формы
ПараметрыФормы = Новый Структура; // Если передаются параметры
ОткрытьФорму("Обработка.МояОбработка.Форма.ВтораяФорма", ПараметрыФормы, ЭтаФорма);
  1. В модуле первой формы создаем экспортную процедуру, которая будет отвечать за обновление интерфейса и перерасчет данных:

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

// Код в модуле второй формы при закрытии или после записи
Если ЗначениеЗаполнено(ВладелецФормы) Тогда
    Попытка
        ВладелецФормы.ОбновитьДанныеНаФорме();
    Исключение
        ЗаписьЖурналаРегистрации("Ошибка обновления формы", УровеньЖурналаРегистрации.Предупреждение,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
    КонецПопытки;
КонецЕсли;

Этот метод обеспечивает полный контроль над процессом обновления, однако создает жесткую связь (зависимость) второй формы от структуры первой.

Метод 3. Использование механизма Оповещений (Слабая связь)

Чтобы избежать жесткой программной привязки дочерней формы к родительской, рекомендуется использовать механизм Оповестить() и предопределенный обработчик ОбработкаОповещения.

Проанализируем этот элегантный способ:

Во второй форме в момент успешной записи данных отправляем глобальное оповещение:


// Код во второй форме
ПараметрыОповещения = Новый Структура;
ПараметрыОповещения.Вставить("Статус", "УспешноЗаписано");
Оповестить("ИзменениеДанныхРегистра", ПараметрыОповещения, ЭтаФорма);

В первой форме переходим в свойства формы, находим событие ОбработкаОповещения, генерируем обработчик и пишем в нем логику обновления:


// Код в модуле первой формы
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ИзменениеДанныхРегистра" Тогда
        // Проверяем параметры, если это необходимо
        Если ТипЗнч(Параметр) = Тип("Структура") И Параметр.Статус = "УспешноЗаписано" Тогда
            ЭлементыФормы.ИмяТабличногоПоля.ОбновитьСтроки();
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Преимущество метода: Вторая форма абсолютно ничего не знает о структуре первой формы. Она лишь отправляет «сигнал» в систему. Любая открытая форма в сеансе пользователя может поймать этот сигнал и обработать его индивидуально.

Реализация аналогичной задачи в Управляемых формах (1С 8.2 / 8.3)

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

Автоматическое обновление динамических списков

В управляемых формах для отображения списков справочников, документов и регистров используется элемент Динамический список.

Если в свойствах динамического списка заполнено свойство Основная таблица (например, указан конкретный регистр сведений), то платформа берет всю рутину на себя. При любой записи в этот регистр из любой другой формы (включая вторую форму) динамический список на первой форме обновится автоматически и мгновенно. Дополнительный код писать не нужно.

Если же ваш динамический список построен на сложном произвольном запросе (без указания основной таблицы), автообновление платформой не гарантируется. В таком случае в первой форме в обработчике оповещения необходимо явно вызвать метод обновления:


&НаКлиенте
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
    Если ИмяСобытия = "ОбновитьРегистр" Тогда
        Элементы.СписокРегистра.Обновить();
    КонецЕсли;
КонецПроцедуры

Асинхронное открытие и возврат результата (Отказ от модальности)

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

В первой форме при инициации открытия второй формы подготавливаем специальный объект ОписаниеОповещения, указывающий на процедуру, которая выполнится сразу после закрытия дочернего окна:


&НаКлиенте
Процедура ОткрытьВторуюФорму(Команда)
    
    // Указываем процедуру-обработчик ожидания завершения
    ОповещениеОЗакрытии = Новый ОписаниеОповещения("ПослеЗакрытияВторойФормы", ЭтаФорма);
    
    // Открываем форму в немодальном режиме
    ОткрытьФорму("Обработка.МояОбработка.Форма.ВтораяФорма", , ЭтаФорма, , , , ОповещениеОЗакрытии);
    
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияВторойФормы(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
    
    // Если пользователь закрыл форму с передачей результата
    Если РезультатЗакрытия = Истина Тогда
        // Выполняем обновление данных на форме
        Элементы.ТаблицаДанных.Обновить();
    КонецЕсли;
    
КонецПроцедуры

Во второй форме при закрытии мы передаем результат работы обратно в вызвавшую форму:


&НаКлиенте
Процедура ЗаписатьИЗакрыть(Команда)
    
    // Выполняем запись данных на сервере
    ЗаписатьДанныеВРегистрНаСервере();
    
    // Закрываем форму и передаем "Истина" как результат успешной работы
    Закрыть(Истина);
    
КонецПроцедуры

Различие методов обновления элементов управления на клиенте

При работе на управляемых формах важно различать три ключевых метода обновления интерфейса:

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

← На главную