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