Как заблокировать кнопку на время выполнения команды и убрать выделение строки в таблице при открытии формы 1С?

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

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

Блокировка кнопки от повторных нажатий

Рассмотрим ситуацию: на форме есть кнопка, запускающая тяжелый алгоритм (например, проведение документов или сложный расчет). Если пользователь нажмет на нее 10 раз подряд очень быстро, платформа поставит эти нажатия в очередь. Как только первый вызов завершится, сразу начнется второй, затем третий и так далее. Простая установка свойства Доступность = Ложь в начале процедуры часто не помогает, так как команда на изменение доступности уходит на сервер вместе с самим вызовом, и пока ответ не вернется на клиент, кнопка остается активной для новых кликов.

Проанализируем наиболее эффективные способы решения этой проблемы.

Способ 1. Использование переменной-флага (самый надежный)

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

Разберем реализацию по шагам:

  1. Объявим переменную в начале модуля формы.
  2. В процедуре команды проверим состояние этой переменной.
  3. Используем конструкцию Попытка...КонецПопытки, чтобы гарантированно сбросить флаг в случае ошибки.

&НаКлиенте
Перем ВыполнениеКомандыИдет;

&НаКлиенте
Процедура ВыполнитьДействие(Команда)
    
    // Если команда уже выполняется, просто выходим
    Если ВыполнениеКомандыИдет = Истина Тогда
        Возврат;
    КонецЕсли;
    
    ВыполнениеКомандыИдет = Истина;
    Элементы.ГруппаКнопки.Доступность = Ложь; // Дополнительно блокируем визуально
    
    Попытка
        ВыполнитьАлгоритмНаСервере();
    Исключение
        ВыполнениеКомандыИдет = Ложь;
        Элементы.ГруппаКнопки.Доступность = Истина;
        ВызватьИсключение;
    КонецПопытки;
    
    ВыполнениеКомандыИдет = Ложь;
    Элементы.ГруппаКнопки.Доступность = Истина;
    
КонецПроцедуры

Способ 2. Обработчик ожидания

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

Рассмотрим пример кода:


&НаКлиенте
Процедура КомандаОК(Команда)
    // Отключаем кнопку немедленно
    Элементы.КомандаОК.Доступность = Ложь;
    // Запускаем алгоритм через короткую паузу (0.1 - 0.2 секунды)
    ПодключитьОбработчикОжидания("ИсполнитьОсновнойАлгоритм", 0.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ИсполнитьОсновнойАлгоритм()
    // Здесь располагается основная логика
    ВыполнитьДействиеНаСервере();
    // Возвращаем доступность
    Элементы.КомандаОК.Доступность = Истина;
КонецПроцедуры

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

Снятие выделения строки в таблице при открытии

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

Выясним причину, почему обычная очистка выделенных строк не работает в процедуре ПриСозданииНаСервере или ПриОткрытии. Дело в том, что после выполнения этих процедур платформа сама дорисовывает интерфейс и принудительно устанавливает фокус согласно своим внутренним правилам.

Решение через управление текущим элементом и сброс строки

Чтобы эффективно убрать выделение, нам нужно выполнить два действия: сбросить ТекущаяСтрока и перевести фокус на другой элемент формы (например, на декоративную надпись или кнопку).

Рассмотрим, как это реализовать в процедуре ПриОткрытии:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    // 1. Убираем фокус с таблицы, перенося его на другой элемент
    ЭтаФорма.ТекущийЭлемент = Элементы.ГруппаЗаголовок; 
    
    // 2. Сбрасываем текущую строку таблицы
    Элементы.СписокТоваров.ТекущаяСтрока = Неопределено;
    
    // 3. Дополнительно очищаем массив выделенных строк (для режима множественного выделения)
    Элементы.СписокТоваров.ВыделенныеСтроки.Очистить();
    
КонецПроцедуры

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


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Подключаем однократный обработчик через 0.1 сек
    ПодключитьОбработчикОжидания("СнятьВыделениеСтроки", 0.1, Истина);
КонецПроцедуры

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

Особенности работы с динамическими списками

Стоит отметить, что для Динамических списков установка ТекущаяСтрока = Неопределено может не сработать, если список еще не загрузил данные. В таких случаях программисты часто используют установку пустой ссылки конкретного типа:

Элементы.Список.ТекущаяСтрока = Справочники.Номенклатура.ПустаяСсылка();

Резюме

Мы проанализировали две специфические проблемы интерфейса 1С. Для предотвращения повторных нажатий кнопок всегда используйте клиентскую переменную-флаг и блокировку группы элементов. Для управления выделением строк в таблицах комбинируйте сброс текущей строки с переносом фокуса на другой нейтральный элемент формы. Использование обработчиков ожидания — это крайняя мера, которая помогает в тех случаях, когда стандартные события формы отрабатывают раньше, чем платформа завершает визуальную отрисовку.

← На главную