Как реализовать позиционирование на элементе в динамическом списке управляемой формы?

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

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

Причина проблемы: Серверный vs Клиентский контекст

Разберем типичную ошибку начинающего разработчика. Попытка установить свойство ТекущаяСтрока в процедуре ПриСозданииНаСервере часто оказывается безрезультатной. Это связано с тем, что на этапе создания формы на сервере таблица динамического списка еще не инициализирована полностью на стороне клиента, и данные в нее подгружаются порциями (ленивая загрузка). Установка текущей строки на сервере может быть перекрыта логикой инициализации формы при ее отображении пользователю.

Способ 1. Использование стандартного параметра «ТекущаяСтрока»

Платформа 1С предоставляет встроенный механизм для позиционирования. Если динамический список является основным реквизитом формы, мы можем передать параметр прямо при вызове метода ОткрытьФорму. Рассмотрим пример кода:


ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ТекущаяСтрока", СсылкаНаНоменклатуру);

ОткрытьФорму("Справочник.Номенклатура.ФормаСписка", ПараметрыФормы);

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

Способ 2. Установка текущей строки в процедуре «ПриОткрытии»

Если автоматическое позиционирование не срабатывает, нам необходимо явно указать строку на стороне клиента. Проанализируем правильную последовательность действий: сначала сохраняем ссылку в реквизит формы на сервере, а затем используем ее при открытии.

В модуле формы реализуем следующий алгоритм:


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

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

Использование ЭтаФорма.ТекущийЭлемент критически важно. Без этой строки 1С может выделить нужный элемент серым цветом (выделение без фокуса), но пользователь этого не заметит, так как фокус останется, например, на поле поиска или кнопке.

Способ 3. Гарантированное позиционирование через временный отбор

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

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

Посмотрим на программную реализацию:


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

&НаКлиенте
Процедура СписокПриАктивизацииСтроки(Элемент)
    Если НужноСнятьОтборПриОткрытии Тогда
        НужноСнятьОтборПриОткрытии = Ложь;
        СнятьОтборПоСсылкеНаСервере();
    КонецЕсли;
КонецПроцедуры

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

Особенности работы с иерархией

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

Почему не работает «НайтиСтроки»?

Важно помнить, что объект ДинамическийСписок на клиенте — это не таблица значений. У него нет метода НайтиСтроки() или Найти(). Это связано с тем, что список не хранит в памяти клиента все записи базы данных одновременно. Он запрашивает лишь те строки, которые видны на экране. Поэтому единственный способ «найти» строку — это передать её идентификатор в ТекущаяСтрока и позволить платформе самой инициировать запрос к серверу для поиска и прокрутки списка к нужной позиции.

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

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

  1. Всегда указывайте Основную таблицу в свойствах списка, если это возможно.
  2. Используйте имена элементов по умолчанию (например, Список), это помогает стандартным механизмам конфигураций (особенно в БСП) корректно обрабатывать параметры.
  3. Если элемент был только что создан программно перед открытием формы, используйте метод ОповеститьОбИзменении(ТипЗнч(Ссылка)). Это заставит динамический список обновить кэш и «увидеть» новую запись для позиционирования.
  4. При программной установке курсора на клиенте всегда устанавливайте ЭтаФорма.ТекущийЭлемент, чтобы пользователь сразу видел результат.

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

← На главную