Как вывести сообщение пользователю при закрытии формы или нажатии Записать и закрыть

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

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

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

Метод 1. Использование механизма оповещений (Notify)

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

Рассмотрим по шагам реализацию этого механизма:

  1. В форме редактируемого объекта (которая будет закрыта) создадим обработчик события ПослеЗаписиНаКлиенте.
  2. В этом обработчике вызовем процедуру Оповестить.

Посмотрим на пример кода в форме элемента:


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

Теперь разберем, что должна сделать форма списка, чтобы «поймать» это сообщение. В форме списка необходимо создать обработчик ОбработкаОповещения.


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

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

Метод 2. Использование ИдентификатораНазначения в СообщениеПользователю

Выясним причину, по которой сообщения пропадают при закрытии. Платформа 1С пытается привязать сообщение к активному окну. Если окно закрывается, сообщение уничтожается вместе с ним. Однако у объекта СообщениеПользователю есть свойство ИдентификаторНазначения, которое позволяет явно указать, в каком окне должно появиться сообщение.

Разберем ситуацию, когда мы открываем форму элемента из формы списка. В этом случае свойство формы ВладелецФормы содержит ссылку на форму списка (или её элемент). Мы можем использовать УникальныйИдентификатор этой формы.


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

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

Метод 3. Передача сообщений с сервера через ДополнительныеСвойства

Часто сообщение порождается в серверном коде, например, в подписке на событие ПередЗаписью. На сервере мы не можем напрямую вызвать Оповестить или работать с клиентскими окнами. Рассмотрим, как передать информацию «наверх» к клиенту.

Проанализируем схему взаимодействия:

  1. В серверной подписке на событие помещаем текст сообщения в ДополнительныеСвойства объекта.
  2. В форме элемента перехватываем эти данные после возврата с сервера.
  3. Выводим их пользователю.

Пример кода в серверном модуле (подписка):


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

Затем в форме элемента (на клиенте) в обработчике ПослеЗаписиНаКлиенте мы можем обратиться к данным объекта. Но помните, что ДополнительныеСвойства не передаются на клиент напрямую автоматически. Нам нужно в серверном методе формы ПриЗаписиНаСервере или ПослеЗаписиНаСервере переложить эти данные в реквизит формы или в параметры, которые вернутся на клиент.


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

Метод 4. Всплывающие уведомления (Toast-сообщения)

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

Посмотрим, как это выглядит в коде:


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

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

Резюме и рекомендации

Подведем итог нашему анализу:

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

← На главную