При работе с управляемыми формами в интерфейсе Такси разработчики часто сталкиваются со стандартным поведением платформы: при интерактивном добавлении новой строки в таблицу (командой "Добавить" или клавишей Insert) система автоматически переводит фокус в первую доступную ячейку и активирует режим редактирования. В большинстве случаев это удобно, однако существуют сценарии, когда такое поведение становится помехой. Разберем ситуацию, проанализируем причины возникновения сложностей и найдем элегантные способы решения этой задачи.
Рассмотрим типичный сценарий: при активизации строки в табличной части нам необходимо выполнить ряд серверных действий (например, проверить остатки, рассчитать скидки или обновить связанные декорации на форме). Поскольку прямые серверные вызовы из обработчика ПриАктивизацииСтроки могут существенно замедлять интерфейс, разработчики часто используют обработчик ожидания.
Проблема заключается в том, что любой контекстный вызов сервера (даже неявный, инициированный платформой или через ПодключитьОбработчикОжидания) приводит к синхронизации состояния формы. Если в этот момент пользователь находится в режиме редактирования ячейки, этот режим может быть принудительно сброшен платформой. Визуально это выглядит крайне неприятно: пользователь начинает вводить данные, окно редактирования внезапно закрывается, фокус "прыгает", и данные теряются. Именно поэтому возникает необходимость добавить строку, но не входить в режим её правки сразу.
Проанализируем самый эффективный способ решения проблемы. Мы можем перехватить событие ПередНачаломДобавления, отменить стандартное действие платформы и добавить строку самостоятельно через код. В этом случае платформа не будет считать, что нужно немедленно "открыть" ячейку для ввода.
Разберем реализацию по шагам:
Отказ = Истина, чтобы заблокировать стандартный механизм добавления.Добавить() для создания новой строки в данных объекта.Пример кода для обработчика события таблицы:
&НаКлиенте
Процедура ТабличнаяЧастьПередНачаломДобавления(Элемент, Отказ, Копирование, Родитель, Группа, Параметр)
// Блокируем стандартное поведение платформы
Отказ = Истина;
// Добавляем строку программно в данные объекта
НоваяСтрока = Объект.ТабличнаяЧасть.Добавить();
// Здесь можно выполнить дополнительные действия,
// например, заполнить реквизиты новой строки
НоваяСтрока.Количество = 1;
// Если нужно, чтобы курсор переместился на новую строку:
Элементы.ТабличнаяЧасть.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
КонецПроцедуры
Важный нюанс: при таком подходе строка добавится в список, выделится цветом (станет текущей), но курсор не перейдет в режим ввода текста. Это позволяет выполнить все фоновые серверные проверки через обработчик ожидания без риска прервать ввод пользователя.
Рассмотрим более сложную ситуацию, когда нам нужно гибко управлять возможностью редактирования в зависимости от состояния фоновых процессов. Мы можем использовать вспомогательную переменную формы (флаг), которая будет блокировать вход в режим правки до тех пор, пока сервер не вернет нужные данные.
Посмотрим на пример логики с использованием переменной РедактированиеРазрешено:
&НаКлиенте
Перем РедактированиеРазрешено; // Флаг состояния
&НаКлиенте
Процедура ТабличнаяЧастьПередНачаломИзменения(Элемент, Отказ)
// Если наши фоновые процессы еще не завершены, запрещаем вход в режим правки
Если РедактированиеРазрешено = Ложь Тогда
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ТабличнаяЧастьПриАктивизацииСтроки(Элемент)
// Сбрасываем флаг и запускаем обработчик ожидания для "грязных дел"
РедактированиеРазрешено = Ложь;
ПодключитьОбработчикОжидания("ВыполнитьФоновыеДействияНаСервере", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьФоновыеДействияНаСервере()
// Здесь выполняем вызов сервера
ОбновитьДанныеСтрокиНаСервере();
// После завершения всех операций разрешаем пользователю редактирование
РедактированиеРазрешено = Истина;
КонецПроцедуры
Этот метод позволяет "заморозить" таблицу на доли секунды, пока выполняются серверные вызовы, предотвращая ситуацию, когда пользователь начинает вводить данные в еще не до конца инициализированную строку.
Выясним, можно ли решить задачу без написания кода. В свойствах элемента формы типа Таблица существует параметр РежимРедактирования. Рассмотрим доступные значения:
F2/Enter.Если установить режим Вход при вводе, то при нажатии кнопки "Добавить" платформа создаст строку, выделит её, но не будет открывать поле ввода первой колонки. Это часто является самым простым и предпочтительным решением, не требующим переопределения стандартных команд.
Проанализируем ситуацию, когда после программного добавления нам всё же нужно перевести фокус на таблицу, но гарантированно избежать активации ячейки. Проверенным "хаком" является принудительная установка текущего элемента формы. Рассмотрим пример:
// Программное добавление
НоваяСтрока = Объект.Товары.Добавить();
Элементы.Товары.ТекущаяСтрока = НоваяСтрока.ПолучитьИдентификатор();
// "Передергиваем" фокус, чтобы сбросить автоматизмы платформы
ЭтаФорма.ТекущийЭлемент = Элементы.ГруппаДекорации; // Уводим фокус на статичный элемент
ЭтаФорма.ТекущийЭлемент = Элементы.Товары; // Возвращаем на таблицу
Такая манипуляция заставляет платформу пересчитать состояние фокуса и часто помогает избежать нежелательного открытия формы редактирования в сложных интерфейсах.
Для того чтобы отменить автоматический вход в режим редактирования новой строки, мы рекомендуем придерживаться следующего алгоритма:
РежимРедактирования на значение Вход при вводе. Это самое чистое решение с точки зрения поддержки кода.ПередНачаломДобавления с параметром Отказ = Истина и программным вызовом Добавить().ПриАктивизацииСтроки обязательно проверяйте, действительно ли изменился идентификатор строки, чтобы не зацикливать серверные вызовы, которые и приводят к "вылету" из режима редактирования.Используя эти методы, вы сделаете интерфейс вашего решения более стабильным и дружелюбным к пользователю, исключив раздражающие прыжки фокуса и потерю введенных данных.