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