Работа с Системой компоновки данных (СКД) в режиме Обычных форм имеет свои специфические особенности, которые часто сбивают с толку даже опытных разработчиков. Одной из наиболее распространенных проблем является ситуация, когда настройки компоновщика (например, отборы) успешно загружаются программно, видны в отладчике, но не отображаются визуально в табличном поле на форме. Рассмотрим подробно, почему это происходит и как правильно реализовать механизм сохранения и восстановления настроек.
Проанализируем механику работы компоновщика. Когда мы размещаем на обычной форме табличное поле и связываем его с путем к данным КомпоновщикНастроек.Настройки.Отбор, платформа создает визуальную связь с конкретным объектом в памяти. Однако при использовании метода ЗагрузитьНастройки() старый объект настроек внутри компоновщика полностью замещается новым. Визуальный элемент управления (табличное поле) продолжает "смотреть" на старый экземпляр объекта, который уже не связан с активным компоновщиком, из-за чего список отборов кажется пустым.
Кроме того, важную роль играет инициализация. Если компоновщик не знает структуру схемы (источник доступных настроек), он не сможет корректно сопоставить загруженные данные с полями компоновки, что также ведет к пустому списку на форме.
Для начала разберем корректный метод сохранения всех реквизитов формы, включая настройки компоновщика, в системное хранилище. Мы будем использовать ХранилищеЗначений для сериализации настроек компоновщика, так как это наиболее надежный способ сохранить структуру НастройкиКомпоновкиДанных.
Процедура СохранитьНастройкиСеанса() Экспорт
СтруктураНастроек = Новый Структура;
пМетаданные = ЭтотОбъект.Метаданные();
// Перебираем реквизиты обработки для сохранения
Для Каждого пРеквизит Из пМетаданные.Реквизиты Цикл
Если пРеквизит.Имя = "КомпоновщикНастроек" Тогда
// Настройки компоновки нужно сохранять через ПолучитьНастройки()
пЗначение = Новый ХранилищеЗначения(ЭтотОбъект[пРеквизит.Имя].ПолучитьНастройки());
Иначе
пЗначение = ЭтотОбъект[пРеквизит.Имя];
КонецЕсли;
СтруктураНастроек.Вставить(пРеквизит.Имя, пЗначение);
КонецЦикла;
// Сохраняем также табличные части, если они есть
Для Каждого пТабличнаяЧасть Из пМетаданные.ТабличныеЧасти Цикл
СтруктураНастроек.Вставить(пТабличнаяЧасть.Имя, ЭтотОбъект[пТабличнаяЧасть.Имя].Выгрузить());
КонецЦикла;
// Записываем структуру в системное хранилище настроек
ХранилищеСистемныхНастроек.Сохранить(ИмяКлючаОбъекта(), КлючНастроекОбщиеНастройки(), СтруктураНастроек);
КонецПроцедуры
В данном примере мы используем ИмяКлючаОбъекта() и КлючНастроекОбщиеНастройки() — это вспомогательные функции, которые должны возвращать уникальные строки для идентификации вашей обработки в базе данных.
Теперь перейдем к самому ответственному моменту — восстановлению. Чтобы настройки "ожили" на форме, необходимо соблюдать строгую последовательность действий: загрузка данных, инициализация источника настроек и принудительное обновление связи с табличным полем.
Выясним причину, почему обычного ЗагрузитьНастройки() бывает недостаточно. Без вызова метода Инициализировать() компоновщик не понимает, какие типы данных допустимы для полей, и визуальный интерфейс блокирует отображение "непонятных" ему элементов.
Процедура ВосстановитьНастройкиСеанса() Экспорт
СтруктураНастроек = ХранилищеСистемныхНастроек.Загрузить(ИмяКлючаОбъекта(), КлючНастроекОбщиеНастройки());
Если СтруктураНастроек = Неопределено Тогда
Возврат;
КонецЕсли;
пМетаданные = ЭтотОбъект.Метаданные();
// Важно: Сначала подготовим источник доступных настроек
// Если схема СКД находится в макете обработки:
СхемаСКД = ЭтотОбъект.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
АдресСхемы = ПоместитьВоВременноеХранилище(СхемаСКД, Новый УникальныйИдентификатор());
ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы);
Для Каждого КлючИЗначение Из СтруктураНастроек Цикл
Если пМетаданные.Реквизиты.Найти(КлючИЗначение.Ключ) <> Неопределено Тогда
Если КлючИЗначение.Ключ = "КомпоновщикНастроек" Тогда
пЗначениеНастроек = КлючИЗначение.Значение.Получить();
Если пЗначениеНастроек <> Неопределено Тогда
// Инициализируем компоновщик перед загрузкой!
ЭтотОбъект.КомпоновщикНастроек.Инициализировать(ИсточникНастроек);
// Загружаем настройки
ЭтотОбъект.КомпоновщикНастроек.ЗагрузитьНастройки(пЗначениеНастроек);
// Восстанавливаем состояние (важно для пользовательских настроек)
ЭтотОбъект.КомпоновщикНастроек.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.Полное);
// КРИТИЧЕСКИЙ МОМЕНТ: Обновляем привязку табличного поля на форме
ОбновитьОтображениеНастроекНаФорме();
КонецЕсли;
Иначе
ЭтотОбъект[КлючИЗначение.Ключ] = КлючИЗначение.Значение;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Как мы уже выяснили, табличное поле часто теряет связь с объектом после его перезагрузки. Рассмотрим метод, который гарантированно заставит форму перерисовать список отборов. Нам нужно вручную переназначить свойство Значение у элемента формы ТабличноеПоле.
Процедура ОбновитьОтображениеНастроекНаФорме()
// Предположим, наше табличное поле на форме называется "ТПОтбор"
// и оно должно отображать отборы компоновщика
ЭлементТП = ЭлементыФормы.ТПОтбор;
// Перепривязываем источник данных
ЭлементТП.Значение = ЭтотОбъект.КомпоновщикНастроек.Настройки.Отбор;
// Принудительно создаем колонки, чтобы обновить визуальную структуру
ЭлементТП.СоздатьКолонки();
КонецПроцедуры
Важный нюанс: Если в вашей схеме компоновки используются не основные настройки, а Пользовательские настройки, то в качестве значения для табличного поля следует указывать КомпоновщикНастроек.ПользовательскиеНастройки. В обычных формах часто путают эти два уровня, что приводит к отсутствию данных в интерфейсе при их фактическом наличии в объекте.
ОтборКомпоновкиДанных.Инициализировать(). Без актуального адреса схемы компоновщик не сможет работать с доступными полями.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.Полное) крайне полезен, когда нужно синхронизировать значения между основными настройками и теми, что выведены в пользовательскую часть.ЭлементыФормы.ВашеПоле.Значение = Неопределено;, а после завершения всех процедур загрузки — вернуть актуальную ссылку. Это провоцирует полную очистку и перерисовку элемента.Следуя этой методике, мы обеспечиваем надежное хранение пользовательских предпочтений и их корректное визуальное представление в интерфейсе обычного приложения 1С.