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

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

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

Разберем основную причину проблемы

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

Шаг 1. Правильное определение ключа строки

Выясним, что именно ожидает динамический список в качестве значения для позиционирования. Если основной таблицей списка является справочник или документ, то ТекущаяСтрока — это Ссылка. Однако, если список построен на базе регистра сведений, обычного идентификатора (например, ID) будет недостаточно. Система ожидает объект типа КлючЗаписиРегистраСведений. Это критично, если вы решили прокачать список и добавить дополнительную информацию через расширения, где ключи могут стать составными.

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


// На сервере формируем структуру ключа
ПараметрыКлюча = Новый Структура;
ПараметрыКлюча.Вставить("ID", НовыйID);
// Добавьте остальные измерения, если они есть
КлючЗаписи = РегистрыСведений.ав_ЗаказыAutoopt.СоздатьКлючЗаписи(ПараметрыКлюча);

Шаг 2. Перенос логики обновления на клиентскую сторону

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

Рассмотрим пример клиентской процедуры после выполнения серверных действий:


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

Шаг 3. Использование механизма оповещений

Если изменения происходят в другой форме или глубоко в серверном вызове, проанализируем использование метода Оповестить. Это наиболее стабильный способ обновления интерфейса, особенно если в вашей системе установлено расширение для отборов на соответствие шаблону, которое может влиять на видимость строк. Посмотрим на алгоритм:

  1. На сервере записываем данные и формируем КлючЗаписи.
  2. На клиенте вызываем Оповестить("ЗаписьИзменена", НовыйКлючЗаписи, ЭтотОбъект);.
  3. В процедуре ОбработкаОповещения текущей формы ловим это событие.

Пример реализации в ОбработкаОповещения:


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

Важные нюансы и рекомендации

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

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

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

← На главную