При работе с многостраничными табличными документами в 1С программисты часто сталкиваются с неприятным визуальным эффектом. Представьте ситуацию: пользователь прокрутил документ далеко вниз, нажал на картинку-гиперссылку, после чего эта картинка удаляется программно. В этот момент интерфейс «прыгает» — документ автоматически прокручивается вверх к той ячейке, которая была активна до взаимодействия с рисунком. Разберем подробно, почему это происходит и как зафиксировать экран в нужной позиции.
Для начала выясним причину такого поведения платформы. В 1С:Предприятии табличный документ разделен на две сущности: данные (объект ТабличныйДокумент) и визуальное представление (элемент формы типа ПолеТабличногоДокумента). Когда пользователь кликает по рисунку, этот рисунок становится активным объектом. Как только мы выполняем команду Удалить() из коллекции рисунков, фокус «теряется», так как объект, на котором он стоял, больше не существует. Система пытается восстановить фокус на последней активной области ячеек. Если эта область находится за пределами видимости (например, в начале документа), происходит мгновенная прокрутка к ней.
Многие разработчики пытаются исправить это, устанавливая свойство ТекущаяОбласть у самого объекта данных. Однако, проанализируем ситуацию: изменение свойства ТекущаяОбласть в объекте ДокументРезультат (ваших данных) сообщает системе, какая область является текущей в контексте структуры данных, но не всегда дает команду интерфейсу немедленно «перемотать» экран в это место. Чтобы управлять именно отображением, нужно обращаться к коллекции Элементы.
Рассмотрим правильный подход. Для того чтобы программно изменить выделение и заставить форму «посмотреть» в нужное место, необходимо обращаться к свойству ТекущаяОбласть не через переменную данных, а через элемент управления на форме. Посмотрим на пример кода, который решает проблему:
// ОПРЕДЕЛЯЕМ ОБЛАСТЬ, КОТОРУЮ НУЖНО СДЕЛАТЬ АКТИВНОЙ
// Например, это ячейка под удаляемым рисунком
НужнаяОбласть = ДокументРезультат.Область(НомерСтрокиПодРисунком, НомерКолонкиПодРисунком);
// УДАЛЯЕМ РИСУНОК
ДокументРезультат.Рисунки.Удалить(ДокументРезультат.Рисунки[ИмяРисунка]);
// ПРАВИЛЬНАЯ УСТАНОВКА ФОКУСА (обращаемся к Элементам формы)
Элементы.ДокументРезультат.ТекущаяОбласть = НужнаяОбласть;
В данном примере ДокументРезультат — это реквизит формы типа ТабличныйДокумент, а Элементы.ДокументРезультат — это визуальный элемент, размещенный на форме. Установка области через элемент формы принудительно перемещает курсор и, что самое важное, удерживает видимую область экрана в нужном месте.
Иногда простой установки ТекущаяОбласть бывает недостаточно, особенно если мы работаем в веб-клиенте или при сложной верстке документа. В таких случаях рекомендуется использовать метод Показать(), который есть у объекта области ячеек. Этот метод специально предназначен для того, чтобы сделать указанную область видимой на экране.
Разберем, как это применить на практике:
// Сначала определяем целевую область
ОбластьЯкорь = ДокументРезультат.Область("R100C2"); // Координаты ячейки, где должен остаться экран
// Удаляем графический объект
ДокументРезультат.Рисунки.Удалить(УдаляемыйРисунок);
// Гарантируем, что экран не "улетит"
ОбластьЯкорь.Показать();
Элементы.ДокументРезультат.ТекущаяОбласть = ОбластьЯкорь;
Метод Показать() дает платформе явное указание выполнить скроллинг к этим координатам. Комбинирование этого метода с установкой ТекущаяОбласть элемента формы дает наиболее стабильный результат.
Проанализируем еще одну стратегию. Чтобы документ не «прыгал» в момент удаления, мы можем перевести фокус с рисунка на ближайшую ячейку до того, как рисунок будет физически удален из коллекции. В этом случае момент удаления объекта не будет сопровождаться потерей активного элемента интерфейса.
Выполним следующие шаги:
Верх, Лево).ТекущаяОбласть в одну из этих ячеек.Удалить() для рисунка.Важный нюанс: Если удаление происходит внутри обработчика события самого рисунка, платформа может блокировать немедленное обновление интерфейса. В этом случае может помочь ПодключитьОбработчикОжидания с минимальным интервалом (например, 0.1 сек), чтобы код установки фокуса выполнился сразу после того, как управление вернется системе.
&НаКлиенте
Процедура ОбработкаНажатияНаРисунок()
// Запоминаем координаты для возврата
ИмяУдаляемогоРисунка = "КнопкаУдалить";
// Вызываем удаление
ДокументРезультат.Рисунки.Удалить(ДокументРезультат.Рисунки[ИмяУдаляемогоРисунка]);
// Используем обработчик ожидания для фиксации фокуса
ПараметрыВызова = Новый Структура("Область", ДокументРезультат.Область(100, 2));
ПодключитьОбработчикОжидания("УстановитьФокусПослеУдаления", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьФокусПослеУдаления()
// Здесь устанавливаем фокус на элемент формы
Элементы.ДокументРезультат.ТекущаяОбласть = ДокументРезультат.Область(100, 2);
КонецПроцедуры
Стоит отметить, что поведение табличного документа может отличаться в зависимости от типа используемого клиента. В мобильном клиенте установка ТекущаяОбласть часто просто перемещает курсор, но не скроллит форму. Для мобильных устройств использование метода Показать() является обязательным условием для управления видимостью.
В веб-клиенте работа с фокусом часто асинхронна. Если вы заметили, что даже после использования Элементы.ДокументРезультат.ТекущаяОбласть «прыжок» сохраняется, попробуйте увеличить задержку в ПодключитьОбработчикОжидания или убедитесь, что вы не вызываете методы ОбновитьОтображениеДанных() слишком часто, так как это может сбрасывать состояние прокрутки к значениям по умолчанию.
Таким образом, для решения проблемы «прыгающего» документа мы должны всегда помнить о разделении данных и их представления. Использование Элементы.ИмяПоля.ТекущаяОбласть вместо Объект.ТекущаяОбласть является ключом к корректному управлению интерфейсом в 1С:Предприятии 8.3.