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