При работе с управляемыми формами 1С программисты часто сталкиваются с неприятной особенностью: после обновления данных в таблице (например, при перезагрузке списка из базы данных или программном изменении состава строк) фокус автоматически «прыгает» на самую первую строку. Это крайне неудобно для пользователя, который работал, скажем, с сотой строкой списка. Разберем по шагам, почему это происходит и как правильно реализовать механизм сохранения активной строки.
Прежде всего, нам необходимо понять внутреннюю механику платформы. В управляемых формах у каждой строки ДанныеФормыКоллекция (которой является таблица на форме) есть два типа «адреса»:
Когда мы вызываем методы типа Загрузить() или полностью обновляем таблицу на сервере, старые объекты строк уничтожаются, а новые создаются «с нуля». Даже если данные в строке остались прежними, её внутренний идентификатор меняется. Свойство таблицы ТекущаяСтрока хранит именно этот внутренний идентификатор. Поскольку старого идентификатора больше не существует, платформа не находит его в новой коллекции и устанавливает фокус на начало списка.
Для того чтобы найти ту же самую строку после обновления, нам нельзя полагаться на индекс или внутренний идентификатор. Нам нужен уникальный ключ из самих данных (например, ссылка на документ, уникальный номер записи или составной ключ из нескольких колонок). Проанализируем ситуацию на примере, где у нас есть колонка ИдентификаторЗаписи.
Перед началом обновления данных на клиенте нам нужно запомнить значение этого ключа:
&НаКлиенте
Процедура ОбновитьДанныеСписка()
// 1. Проверяем, есть ли вообще выбранная строка
ТекущиеДанные = Элементы.ДанныеСписка.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
КлючСтроки = Неопределено;
Иначе
// Сохраняем уникальный идентификатор из наших данных
КлючСтроки = ТекущиеДанные.ИдентификаторЗаписи;
КонецЕсли;
// 2. Вызываем серверную процедуру обновления
ОбновитьДанныеНаСервере();
// 3. Переходим к поиску и позиционированию (см. Шаг 2)
ПозиционироватьНаСтроку(КлючСтроки);
КонецПроцедуры
Как показывает практика, использование простого метода Загрузить() для таблицы значений иногда приводит к тому, что визуальная часть формы не успевает корректно отработать изменения. Рассмотрим более надежный способ через работу с объектом и преобразование его в реквизит формы.
&НаСервере
Процедура ОбновитьДанныеНаСервере()
Запрос = Новый Запрос("ВЫБРАТЬ * ИЗ РегистрСведений.НашРегистр ГДЕ ...");
ТаблицаРезультат = Запрос.Выполнить().Выгрузить();
// Использование ЗначениеВРеквизитФормы часто работает стабильнее,
// так как платформа более явно отслеживает изменение коллекции
ЗначениеВРеквизитФормы(ТаблицаРезультат, "ДанныеСписка");
КонецПроцедуры
После того как данные обновились, нам нужно найти в новой коллекции строку, у которой ИдентификаторЗаписи совпадает с сохраненным. Найдя строку, мы должны получить её новый внутренний идентификатор с помощью метода ПолучитьИдентификатор().
&НаКлиенте
Процедура ПозиционироватьНаСтроку(КлючСтроки)
Если КлючСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
// Ищем строки в коллекции по нашему бизнес-ключу
ПараметрыПоиска = Новый Структура("ИдентификаторЗаписи", КлючСтроки);
НайденныеСтроки = ДанныеСписка.НайтиСтроки(ПараметрыПоиска);
Если НайденныеСтроки.Количество() > 0 Тогда
// Получаем ПЕРВУЮ найденную строку (объект ДанныеФормыЭлементКоллекции)
СтрокаКоллекции = НайденныеСтроки[0];
// Важный момент: устанавливаем ТекущуюСтроку через внутренний идентификатор
Элементы.ДанныеСписка.ТекущаяСтрока = СтрокаКоллекции.ПолучитьИдентификатор();
КонецЕсли;
КонецПроцедуры
Часто разработчики жалуются: «Я установил ТекущаяСтрока, строка выделилась цветом, но пунктирная рамка (фокус) всё равно осталась на первой строке или выделились сразу две». Это происходит из-за рассинхронизации визуального состояния таблицы и данных.
Чтобы этого избежать, проанализируем следующие рекомендации:
Элементы.ДанныеСписка.ВыделенныеСтроки.Очистить();
Элементы.ДанныеСписка.ТекущаяСтрока = НовыйИдентификатор;
&НаКлиенте
Процедура ОбновитьДанныеСписка()
// ... сохранение ключа ...
ОбновитьДанныеНаСервере();
// Передаем КлючСтроки в обработчик ожидания
ПараметрыВызова = Новый Массив;
ПараметрыВызова.Добавить(КлючСтроки);
ПодключитьОбработчикОжидания("ВыполнитьОтложенноеПозиционирование", 0.1, Истина);
КонецПроцедуры
ТекущаяСтрока могут быть не видны визуально до тех пор, пока пользователь не кликнет по таблице. Выполните ЭтаФорма.ТекущийЭлемент = Элементы.ДанныеСписка;.Подводя итог, можно сказать, что стабильное сохранение строки в управляемых формах 1С требует комбинации трех факторов: использования бизнес-ключа для поиска, получения актуального внутреннего идентификатора и, в сложных случаях, использования обработчика ожидания для завершения визуальной отрисовки формы платформой.