Как правильно обработать одиночный клик по строке динамического списка в 1С?

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

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

В этой статье мы подробно разберем, как «отловить» именно осознанный клик пользователя, исключить лишние срабатывания и сделать интерфейс отзывчивым и профессиональным.

Анализ проблемы: почему стандартные события срабатывают слишком часто?

Давайте проанализируем ситуацию. Динамический список — это сложный объект, который подгружает данные порциями. Событие ПриАктивизацииСтроки вызывается платформой в следующих случаях:

  1. При первичной загрузке формы, когда система позиционируется на первой строке.
  2. При программном обновлении списка или изменении параметров запроса.
  3. При навигации с помощью клавиатуры (стрелки вверх/вниз).
  4. При реальном клике мышкой по строке.

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

Способ 1: Использование обработчика ожидания (Debounce)

Это, пожалуй, самый элегантный и надежный способ. Идея заключается в том, чтобы не выполнять действие мгновенно, а подождать короткий промежуток времени (например, 0.1 или 0.2 секунды). Если за это время пользователь переключился на другую строку, мы сбрасываем ожидание и начинаем отсчет заново. Это позволяет отсечь «дребезг» при быстром пролистывании списка.

Рассмотрим пример реализации:


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

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

Такой подход визуально воспринимается пользователем как мгновенная реакция на клик, но при этом система не перегружается лишними вызовами при инициализации списка.

Способ 2: Сравнение с предыдущим значением (Кэширование)

Проанализируем ситуацию, когда событие вызывается несколько раз для одной и той же строки (например, при обновлении формы). Чтобы избежать повторного выполнения одного и того же кода, мы можем запоминать последнюю обработанную ссылку.

Для этого создадим реквизит формы ПоследнийОбработанныйСотрудник с типом ссылки на объект.


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

Способ 3: Проверка фокуса через ТекущийЭлемент

Бывают случаи, когда событие срабатывает, когда фокус вообще находится в другом месте (например, при открытии вспомогательного окна). Мы можем добавить проверку, активен ли в данный момент сам список.

Рассмотрим код с проверкой фокуса:


&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    
    // Если фокус не на таблице, скорее всего это системный вызов при инициализации
    Если ЭтаФорма.ТекущийЭлемент <> Элементы.Список Тогда
        Возврат;
    КонецЕсли;
    
    // Дальнейшая логика обработки...
    
КонецПроцедуры

Способ 4: Использование гиперссылки с правильным оформлением

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

Выясним, как сделать гиперссылку визуально неотличимой от обычного текста, сохранив её функционал:

  1. Выберите нужную колонку в дереве элементов формы.
  2. Установите свойство Вид в значение Поле гипперссылки.
  3. В свойстве ЦветТекстаГиперссылки выберите Авто-текст (или явно задайте черный/стандартный цвет).
  4. В настройках шрифта колонки уберите галочку Подчеркивание.
  5. Создайте обработчик события Нажатие для этой колонки.

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

Способ 5: Вычисляемое поле «Выбор» (Флажок)

Если задача стоит именно в «выборе» конкретного сотрудника для дальнейшей работы, рассмотрим вариант с добавлением колонки-флажка (тип Булево). Вы можете добавить в запрос динамического списка фиктивное поле ВЫБРАТЬ ЛОЖЬ КАК Выбран (если не планируете сохранять этот выбор в БД).

В этом случае вы будете обрабатывать событие ПриИзменении этого флажка. Это гарантирует 100% точность: действие будет выполнено только тогда, когда пользователь целенаправленно нажал на чекбокс.

Резюме и рекомендации

Мы рассмотрели основные подходы к обработке клика в динамическом списке. Подведем итоги:

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

← На главную