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

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

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

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

Выясним причину: почему сбрасываются данные

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

Проанализируем основные причины сброса выделения:

  1. Неявные контекстные серверные вызовы: Это самая частая причина. Даже если на событие ПриСменеСтраницы не назначен обработчик, при переключении закладок могут срабатывать другие события, такие как ПриАктивизацииЭлемента или ПриАктивизацииОбласти. Если в этих процедурах вызывается серверный метод с директивой &НаСервере, платформа выполняет полную синхронизацию контекста формы.
  2. Обновление идентификаторов строк: Если в коде используются конструкции РеквизитФормыВЗначение и последующая обратная конвертация ЗначениеВДанныеФормы, платформа полностью пересоздает коллекцию строк таблицы. С точки зрения системы это абсолютно новая таблица, и старые идентификаторы строк (ID) становятся невалидными. Курсор закономерно прыгает на первую строку.
  3. Динамические списки и автообновление: Если на форме присутствуют динамические списки с коротким интервалом обновления или фоновые процессы, они могут инициировать перерисовку всей формы в момент смены фокуса.

Решение 1: Проверка контекстных серверных вызовов

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


&НаКлиенте
Процедура ПриАктивизацииЭлемента(Элемент)
    // Если этот код срабатывает при переключении страницы, 
    // происходит передача всей формы на сервер
    ОбработатьДанныеНаСервере(); 
КонецПроцедуры

&НаСервере
Процедура ОбработатьДанныеНаСервере()
    // Любые манипуляции здесь могут привести к обновлению ТЗ
КонецПроцедуры

Чтобы избежать этой проблемы, проанализируем ситуацию: действительно ли нам нужен контекст формы? Если нет, используйте директиву &НаСервереБезКонтекста. Это исключит передачу данных формы на сервер и обратно, сохранив состояние элементов управления нетронутым.

Решение 2: Ручное сохранение позиции текущей строки

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

Разберем по шагам, как это реализовать:

  1. Создадим реквизит формы ТекущийИдентификаторСтроки (тип: Число).
  2. В обработчике, который предшествует обновлению данных, сохраним позицию.
  3. После завершения серверных операций восстановим позицию.

Пример реализации:


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

Важный нюанс: Этот метод сработает только в том случае, если идентификаторы строк не изменились (например, не было полной перезагрузки таблицы из объекта ТаблицаЗначений).

Решение 3: Оптимизация работы с РеквизитФормыВЗначение

Если ваша логика требует преобразования таблицы в объект типа ТаблицаЗначений для использования методов НайтиСтроки или Свернуть, помните, что обратная загрузка ЗначениеВДанныеФормы — это "тяжелая" операция для интерфейса.

Рассмотрим, как правильно выполнять такие преобразования, чтобы не "пугать" пользователя прыгающим курсором:


&НаСервере
Процедура ОбновитьТаблицуБезПотериПозиции()
    
    // Переводим данные формы в прикладной объект
    ТЗ = РеквизитФормыВЗначение("Объект.Товары");
    
    // Выполняем действия, например, сортировку
    ТЗ.Сортировать("Номенклатура Возр");
    
    // Загружаем обратно
    ЗначениеВДанныеФормы(ТЗ, Объект.Товары);
    
    // Платформа обновила ID строк, здесь может потребоваться 
    // дополнительный поиск соответствия старых строк новым
    
КонецПроцедуры

Чтобы избежать полной потери фокуса при использовании ЗначениеВДанныеФормы, старайтесь обновлять только те колонки, которые изменились, обращаясь к элементам коллекции напрямую через Объект.Товары[Индекс], не конвертируя всю таблицу целиком.

Решение 4: Использование события ПриСменеСтраницы

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

Проанализируем пример использования события ПриСменеСтраницы для панели ГруппаСтраницы:


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

Рекомендации по настройке элементов формы

Помимо программного кода, обратите внимание на свойства самой таблицы в конфигураторе:

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

← На главную