Почему не переключается страница панели программно после обновления платформы 1С и как это исправить?

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

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

Суть проблемы: почему страница «отпрыгивает» назад?

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

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

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

Решение №1: Использование обработчика ожидания (рекомендуемый способ)

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

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


Процедура ТабличноеПоле1Выбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
    // Вместо прямого переключения:
    // ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.Сделки;
    
    // Подключаем процедуру-обертку с минимальным интервалом
    ПодключитьОбработчикОжидания("ВыполнитьПереключениеНаСтраницуСделки", 0.1, Истина);
КонецПроцедуры

Процедура ВыполнитьПереключениеНаСтраницуСделки()
    // Этот код выполнится в отдельном потоке событий
    ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.Сделки;
КонецПроцедуры

В данном примере параметр Истина в методе ПодключитьОбработчикОжидания означает, что процедура выполнится однократно. Интервала в 0.1 секунды достаточно, чтобы системные механизмы фокуса завершили свою работу.

Решение №2: Оптимизация обращения к страницам

Посмотрим на пример кода, который часто используют разработчики: использование метода Найти(). Хотя это не является прямой причиной «отскока» страницы, это делает код менее надежным. Если страница не будет найдена, метод вернет Неопределено, и попытка присвоения вызовет ошибку. Выясним, как писать правильнее.

Если имя страницы известно заранее, лучше обращаться к ней напрямую через коллекцию Страницы. Сравним два варианта:

Плохой вариант:


ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.Найти("Сделки");

Хороший вариант:

ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.Сделки;

Прямое обращение через точку работает быстрее и позволяет избежать лишних проверок на Неопределено, если структура формы статична.

Решение №3: Принудительная активизация элемента на новой странице

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

  1. Устанавливаем новую текущую страницу.
  2. Явно назначаем ТекущийЭлемент формы.

Процедура ТабличноеПоле1Выбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
    ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.Сделки;
    // Пытаемся «перетянуть» фокус на элемент новой страницы
    ЭтаФорма.ТекущийЭлемент = ЭлементыФормы.КнопкаОформитьЗаказ;
КонецПроцедуры

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

Дополнительные рекомендации по асинхронности

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

Проанализируем еще несколько моментов, которые могут влиять на результат:

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

← На главную