В разработке на платформе 1С:Предприятие 8.3 часто возникают ситуации, когда стандартные механизмы динамического списка ведут себя непредсказуемо. Несмотря на то, что существуют несколько приемов построения эффективных интерфейсов, о которых мало кто знает, одной из частых проблем остается невозможность программно установить фокус на конкретную строку после обновления списка. Особенно остро этот вопрос стоит в случаях, когда динамический список (ДС) построен на базе произвольного запроса, объединяющего несколько таблиц, и у него не задана ОсновнаяТаблица. Разберем подробно, почему так происходит и как заставить интерфейс подчиняться нашим командам.
Рассмотрим стандартную ситуацию: разработчик пытается присвоить значение свойству ТекущаяСтрока, используя ссылку на документ или справочник. Однако, если в настройках динамического списка не указана Основная таблица, платформа теряет жесткую связь между данными в базе и строками в визуальном элементе. Система просто «не понимает», что именно является уникальным идентификатором в текущем наборе данных. Выясним, какие шаги необходимо предпринять для исправления этой ситуации.
Проанализируем работу динамического списка. В целом, настройка списка по щучьему веленью (через компоновщик или конфигуратор) позволяет гибко управлять данными, но когда свойство ОсновнаяТаблица не заполнено, поле ТекущаяСтрока ожидает не просто ссылку, а значение, которое определено в качестве Поля ключа. Без этого программная установка текущей строки в 99% случаев игнорируется.
Выполним следующие действия:
Кстати, на этапе формирования запроса полезно знать, как добавить дополнительную информацию в динамический список с помощью расширения или создать новые вычисляемые поля, чтобы идентификатор был однозначным.
Посмотрим на пример создания составного ключа в запросе:
ВЫБРАТЬ
Т.Ссылка КАК Ссылка,
Т.Дата КАК Дата,
ВЫРАЗИТЬ(Т.Ссылка КАК СТРОКА(36)) + "_" + ВЫРАЗИТЬ(Т.Номер КАК СТРОКА(10)) КАК УникальныйИдентификаторСтроки
ИЗ
Документ.РеализацияТоваровУслуг КАК Т
В данном случае в качестве Поля ключа в настройках ДС нужно указать УникальныйИдентификаторСтроки. Теперь при попытке активировать строку программно, мы должны передавать именно это значение:
НужныйКлюч = Строка(ДокументСсылка) + "_" + НомерДокумента;
Элементы.Список.ТекущаяСтрока = НужныйКлюч;
Иногда даже при верных настройках ключа строка не активируется. Разберем причину: динамический список обновляется асинхронно. Когда мы вызываем метод Обновить() и следом пытаемся установить строку, данные с сервера еще не успевают «долететь» до клиента. Платформа пытается найти строку, которой в локальном кеше еще нет.
Для решения этой проблемы применим небольшую хитрость с ПодключитьОбработчикОжидания. Это позволит платформе завершить отрисовку интерфейса перед выполнением кода активации.
Рассмотрим пример реализации:
&НаКлиенте
Процедура КомандаОбновитьИАктивировать(Команда)
// Сохраняем идентификатор, который нужно активировать
ПараметрАктивации = Элементы.Список.ТекущиеДанные.Ссылка;
// Обновляем список
Элементы.Список.Обновить();
// Вызываем активацию через паузу
ПараметрыВызова = Новый Структура("Ключ", ПараметрАктивации);
ПодключитьОбработчикОжидания("УстановитьТекущуюСтрокуЗавершение", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьТекущуюСтрокуЗавершение()
// Теперь, когда данные обновились, установка сработает
Элементы.Список.ТекущаяСтрока = ПараметрАктивации;
КонецПроцедуры
Если данные в информационной базе изменились программно (например, в фоновом задании или другой форме), и нам нужно, чтобы список не просто обновился, но и «подхватил» новую активную строку, рекомендуется использовать метод ОтобразитьИзменениеДанных. Это заставляет форму перечитать данные более агрессивно, чем обычное Обновить().
Посмотрим, как это выглядит в коде:
// Оповещаем систему об изменении конкретного объекта
ОтобразитьИзменениеДанных(НужнаяСсылка, ИзменениеДанныхВид.Изменение);
// После этого установка строки становится стабильнее
Элементы.Список.ТекущаяСтрока = НужнаяСсылка;
В некоторых случаях ТекущаяСтрока может конфликтовать с внутренними механизмами платформы (особенно в веб-клиенте). Если вы реализовали программное перемещение колонки динамического списка, то логика фокуса может усложниться. Тогда мы можем воздействовать напрямую на коллекцию ВыделенныеСтроки. Это визуально подсвечивает нужный элемент и зачастую заставляет список прокрутиться к нему.
Рассмотрим по шагам:
ТекущаяСтрока в то же значение для фиксации фокуса.
Элементы.Список.ВыделенныеСтроки.Очистить();
Элементы.Список.ВыделенныеСтроки.Добавить(НужныйИдентификаторКлюча);
Элементы.Список.ТекущаяСтрока = НужныйИдентификаторКлюча;
Проанализируем ситуацию, описанную в сообщениях форума. Если ваш запрос слишком сложный, не имеет однозначного поля ключа, а пользователю постоянно требуется точное позиционирование после манипуляций с данными, возможно, стоит заменить Динамический список на Таблицу Значений (ТЗ). В этом случае вам пригодится инструкция про программный вывод произвольной таблицы значений на управляемую форму.
Преимущества ТЗ в данном контексте:
Найти() или НайтиСтроки() работает мгновенно и предсказуемо.ПолучитьИдентификатор() гарантирует 100% срабатывание ТекущаяСтрока.Рассмотрим код активации для Таблицы Значений:
// Поиск строки в коллекции ДанныеФормыКоллекция
СтрокаТЗ = Объект.МояТаблица.НайтиСтроки(Новый Структура("Документ", ИскомыйДокумент));
Если СтрокаТЗ.Количество() > 0 Тогда
Идентификатор = СтрокаТЗ[0].ПолучитьИдентификатор();
Элементы.МояТаблица.ТекущаяСтрока = Идентификатор;
КонецЕсли;
Мы выяснили, что для успешной активации строки в динамическом списке без основной таблицы критически важно наличие Поля ключа и правильный тайминг выполнения операции. Помните, что использование 0.1 секунды в обработчике ожидания — это не «костыль», а необходимая мера синхронизации клиентского интерфейса с асинхронным процессом получения данных в ДС. Применяйте эти методы в зависимости от сложности вашего интерфейса и требований к производительности.