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