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

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

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

В этой статье мы подробно разберем, почему стандартный поиск ведет себя именно так, как обойти ограничение с фокусом ввода с помощью кастомного поиска, и рассмотрим рабочие сценарии программной очистки отборов динамического списка.

Ограничение платформенного поиска: почему требуется нажатие Enter?

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

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

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

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

Реализация кастомного поиска при вводе символов (Паттерн Debounce)

Если мы просто создадим текстовое поле на форме и привяжем наложение отбора к событию ИзменениеТекстаРедактирования, то столкнемся с проблемой «фриза» интерфейса. При вводе каждого символа форма будет выполнять серверный вызов для фильтрации списка, фокус будет «улетать» из поля ввода, и пользователь не сможет комфортно набрать даже короткое слово.

Чтобы решить эту проблему, применим классический паттерн программирования интерфейсов — Debounce (отложенное выполнение) через обработчик ожидания. Суть метода заключается в том, что отбор накладывается не моментально при вводе буквы, а только тогда, когда пользователь сделал небольшую паузу в наборе (например, 0.5 секунды).

Рассмотрим по шагам, как это реализовать:

  1. Создадим реквизит формы с именем СтрокаПоиска (тип Строка) и вынесем его на форму над динамическим списком в виде поля ввода.
  2. Для нового поля ввода создадим обработчик события ИзменениеТекстаРедактирования.
  3. Добавим еще один вспомогательный реквизит формы ВременныйТекстПоиска (тип Строка), в котором будем хранить промежуточное состояние ввода.

Проанализируем программный код для модуля управляемой формы:


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

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


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

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

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

Как программно очистить платформенный поиск (Ctrl + F)?

Рассмотрим другую проблему: пользователь воспользовался стандартным поиском платформы (нажал Ctrl + F или просто начал вводить текст на списке), выбрал нужную строку (например, перенес товар в документ двойным кликом), и теперь нам нужно программно сбросить этот отбор, чтобы вернуть список к исходному полному виду.

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

Рассмотрим три варианта решения этой задачи:

Вариант 1. Отказ от платформенной строки поиска (Рекомендуемый)

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

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

При таком подходе сброс поиска при выборе элемента или по нажатию кнопки «Очистить» выполняется элементарно в одну строку кода на клиенте:


&НаКлиенте
Процедура СброситьКастомныйПоиск()
    
    СтрокаПоиска = "";
    ВременныйТекстПоиска = "";
    УстановитьФильтрСпискаНаСервере("");
    
КонецПроцедуры

Вариант 2. Обходной путь через эмуляцию нажатия клавиш (Только для Windows)

Если по каким-то причинам критически важно сохранить именно стандартную поисковую панель 1С, но при этом требуется программно сбрасывать ее результаты, можно воспользоваться эмуляцией нажатия горячих клавиш очистки поиска. В платформе 1С:Предприятие за сброс поиска отвечает сочетание клавиш Ctrl + Q (в зависимости от раскладки клавиатуры и версии платформы также может использоваться Ctrl + Shift + Q).

Мы можем вызвать эту команду программно через интерфейс операционной системы Windows:


&НаКлиенте
Процедура СброситьСтандартныйПоискWindows()
    
    #Если Клиент Тогда
    Попытка
        // Создаем COM-объект операционной системы для работы со сценариями
        Шелл = Новый COMОбъект("Wscript.Shell");
        
        // Обязательно активизируем элемент формы (таблицу списка)
        Элементы.Список.Активизировать();
        
        // Посылаем команду нажатия Ctrl + Q для английской раскладки
        Шелл.SendKeys("^q");
        
        // Посылаем команду нажатия Ctrl + Й для русской раскладки
        Шелл.SendKeys("^й");
    Исключение
        // Данный код не сработает в веб-клиенте, на MacOS или Linux
    КонецПопытки;
    #КонецЕсли
    
КонецПроцедуры

Важное предупреждение: данный метод является нестабильным обходным путем (workaround). Он зависит от текущей раскладки клавиатуры пользователя, загруженности процессора и операционной системы. Использовать его рекомендуется только в крайних случаях, когда другие варианты невозможны.

Вариант 3. Переинициализация формы (Грубый метод)

Если требуется гарантированно очистить все кэшированные платформой отборы и настройки поиска, но при этом недопустимо использовать внешние COM-объекты, можно прибегнуть к переоткрытию формы. При закрытии и повторном открытии формы с передачей ключа текущего объекта для позиционирования платформа полностью пересоздает контекст, стирая историю поиска.

Однако помните, что этот метод приводит к визуальному «миганию» экрана и создает дополнительную нагрузку на сервер СУБД, так как форма инициализируется заново. Используйте его только тогда, когда чистота интерфейса важнее производительности.

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

← На главную