Как сохранить и восстановить текущую строку в таблице управляемой формы после серверного вызова

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

При разработке на платформе 1С:Предприятие 8.3 (Управляемые формы) программисты часто сталкиваются с неприятным поведением интерфейса: после изменения значения в ячейке таблицы и выполнения серверной процедуры фокус (активная строка) «прыгает» на самую первую строку списка. Это происходит даже в том случае, если в коде явно прописано присвоение сохраненного значения ТекущаяСтрока. Давайте разберем, почему стандартный подход не работает и как правильно реализовать активацию нужной строки.

Выясним причину: почему идентификаторы «протухают»

Для начала проанализируем ситуацию, описанную в коде автора. Мы видим попытку сохранить ТекущаяСтрока в переменную, выполнить серверную процедуру ДатаПриИзмененииНаСервере() и затем вернуть фокус обратно. Однако на практике Элементы.ТабБДДС.ТекущаяСтрока = ТекущаяСтрока игнорируется системой.

Основная причина кроется в механизме работы управляемых форм. В объектах типа ДанныеФормыКоллекция (которыми являются таблицы на форме) свойство ТекущаяСтрока содержит не индекс (0, 1, 2...), а внутренний идентификатор строки. Этот идентификатор уникален и постоянен только до тех пор, пока данные в таблице не будут пересозданы.

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

Решение №1: Поиск строки по ключевым полям

Разберем самый надежный способ решения проблемы. Поскольку мы не можем полагаться на идентификатор, нам нужно найти строку по ее содержимому. Для этого в таблице должно быть поле (или комбинация полей), значения в котором уникальны для каждой строки (например, «НомерСтроки», «Артикул», «GUID» или ссылка на документ).

Рассмотрим алгоритм действий по шагам:

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

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


&НаКлиенте
Процедура ТабБДДСПриИзменении(Элемент)
    
    // 1. Сохраняем ключевые данные текущей строки (не идентификатор!)
    ТекущиеДанные = Элемент.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Допустим, у нас есть колонка "КлючСвязи" или "НомерСтроки"
    СохраненныйКлюч = ТекущиеДанные.КлючСвязи;
    
    ОчиститьСообщения();
    
    // 2. Выполняем серверную операцию, которая обновляет таблицу
    Если Не мПризнакДобавленияСтроки Тогда
        ДатаПриИзмененииНаСервере();
    КонецЕсли;
    
    // 3. Ищем строку в обновленной коллекции по сохраненному ключу
    ПараметрыПоиска = Новый Структура("КлючСвязи", СохраненныйКлюч);
    НайденныеСтроки = Объект.ТабБДДС.НайтиСтроки(ПараметрыПоиска);
    
    Если НайденныеСтроки.Количество() > 0 Тогда
        // 4. Получаем НОВЫЙ идентификатор обновленной строки
        НовыйИдентификатор = НайденныеСтроки[0].ПолучитьИдентификатор();
        Элементы.ТабБДДС.ТекущаяСтрока = НовыйИдентификатор;
    КонецЕсли;
    
    мПризнакДобавленияСтроки = Ложь;
    
КонецПроцедуры

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

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

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

Реализуем это следующим образом:


&НаКлиенте
Перем КлючДляВосстановления; // Переменная модуля формы

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

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

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

При работе с позиционированием строк стоит обратить внимание на следующие моменты:

Подведем итог: Главный секрет стабильной работы фокуса в 1С — никогда не доверять идентификаторам строк после серверных вызовов. Всегда используйте бизнес-логику (уникальные поля данных) для восстановления контекста пользователя. Рассмотренные нами методы поиска по ключу и использования обработчика ожидания являются стандартом «хорошего тона» при разработке сложных интерфейсов на управляемых формах.

← На главную