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

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

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

Анализируем причину проблемы

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

Решение 1: Настройка «Поля ключа»

Проанализируем работу динамического списка. В целом, настройка списка по щучьему веленью (через компоновщик или конфигуратор) позволяет гибко управлять данными, но когда свойство ОсновнаяТаблица не заполнено, поле ТекущаяСтрока ожидает не просто ссылку, а значение, которое определено в качестве Поля ключа. Без этого программная установка текущей строки в 99% случаев игнорируется.

Выполним следующие действия:

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

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

Посмотрим на пример создания составного ключа в запросе:


ВЫБРАТЬ
    Т.Ссылка КАК Ссылка,
    Т.Дата КАК Дата,
    ВЫРАЗИТЬ(Т.Ссылка КАК СТРОКА(36)) + "_" + ВЫРАЗИТЬ(Т.Номер КАК СТРОКА(10)) КАК УникальныйИдентификаторСтроки
ИЗ
    Документ.РеализацияТоваровУслуг КАК Т

В данном случае в качестве Поля ключа в настройках ДС нужно указать УникальныйИдентификаторСтроки. Теперь при попытке активировать строку программно, мы должны передавать именно это значение:


НужныйКлюч = Строка(ДокументСсылка) + "_" + НомерДокумента;
Элементы.Список.ТекущаяСтрока = НужныйКлюч;

Решение 2: Использование обработчика ожидания

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

Для решения этой проблемы применим небольшую хитрость с ПодключитьОбработчикОжидания. Это позволит платформе завершить отрисовку интерфейса перед выполнением кода активации.

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


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

&НаКлиенте
Процедура УстановитьТекущуюСтрокуЗавершение()
    // Теперь, когда данные обновились, установка сработает
    Элементы.Список.ТекущаяСтрока = ПараметрАктивации;
КонецПроцедуры

Решение 3: Метод «ОтобразитьИзменениеДанных»

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

Посмотрим, как это выглядит в коде:


// Оповещаем систему об изменении конкретного объекта
ОтобразитьИзменениеДанных(НужнаяСсылка, ИзменениеДанныхВид.Изменение);

// После этого установка строки становится стабильнее
Элементы.Список.ТекущаяСтрока = НужнаяСсылка;

Решение 4: Программное управление коллекцией «ВыделенныеСтроки»

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

Рассмотрим по шагам:

  1. Очистим текущее выделение.
  2. Добавим в коллекцию идентификатор нужной строки.
  3. Установим ТекущаяСтрока в то же значение для фиксации фокуса.

Элементы.Список.ВыделенныеСтроки.Очистить();
Элементы.Список.ВыделенныеСтроки.Добавить(НужныйИдентификаторКлюча);
Элементы.Список.ТекущаяСтрока = НужныйИдентификаторКлюча;

Когда стоит отказаться от динамического списка?

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

Преимущества ТЗ в данном контексте:

Рассмотрим код активации для Таблицы Значений:


// Поиск строки в коллекции ДанныеФормыКоллекция
СтрокаТЗ = Объект.МояТаблица.НайтиСтроки(Новый Структура("Документ", ИскомыйДокумент));
Если СтрокаТЗ.Количество() > 0 Тогда
    Идентификатор = СтрокаТЗ[0].ПолучитьИдентификатор();
    Элементы.МояТаблица.ТекущаяСтрока = Идентификатор;
КонецЕсли;

Подведение итогов

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

← На главную