В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 начинающие программисты часто сталкиваются с задачей отображения графической информации. Типичный сценарий: в системе есть справочник Модели, где хранится фотография автомобиля, и справочник Оборудование (или ТранспортныеСредства), в котором пользователь выбирает модель. Логично, что при выборе модели на форме оборудования должна автоматически появляться соответствующая фотография.
В этой статье мы подробно разберем, почему возникают популярные ошибки при работе с картинками в управляемом приложении, проанализируем клиент-серверное взаимодействие и реализуем оптимальный, быстродействующий механизм динамического отображения фото.
Для начала разберем типичные ошибки, которые совершают разработчики при решении подобных задач. Проанализируем строку кода, на которую ругался компилятор у автора темы:
Фото.Объект.Картинка.Получить;
В этой короткой строке скрыты сразу три фундаментальные ошибки работы в управляемом интерфейсе:
Фото на клиенте представляет собой обычную строку (навигационную ссылку или адрес во временном хранилище). У типа Строка нет и не может быть свойства Объект. Платформа закономерно сообщает об ошибке: «Значение не является значением объектного типа (Объект)».Объект.Модель.Картинка на клиенте вызовет критическую ошибку, так как клиентское приложение «знает» только ссылочные метаданные, но не имеет прямого доступа к таблицам СУБД. Любое чтение данных должно происходить на сервере.Получить() используется для извлечения данных из объекта типа ХранилищеЗначения. Однако на форме мы работаем с навигационными ссылками, которые платформа 1С визуализирует в поле картинки автоматически, без необходимости ручного извлечения двоичных данных в память клиента.Также частой ошибкой является обновление картинки только в процедуре ПриСозданииНаСервере. При таком подходе, если пользователь интерактивно изменит модель в открытой карточке оборудования, картинка останется прежней до тех пор, пока форму не переоткроют. Нам же требуется динамическое интерактивное обновление.
Давайте спроектируем правильную структуру данных. Нам понадобятся три объекта конфигурации:
Файл с типом ХранилищеЗначения.Картинка с типом ссылки на справочник Файлы.Модель с типом ссылки на справочник МоделиТСиОборудования. Именно на форме этого справочника мы будем выводить фотографию выбранной модели.Такое разделение позволяет хранить тяжелые файлы отдельно от основных учетных данных, что положительно сказывается на производительности СУБД при выборках.
Рассмотрим подробнее процесс настройки формы и написания программного кода для реализации динамического отображения фото.
Откроем управляемую форму элемента справочника ТранспортныеСредства (или Оборудование) и выполним следующие действия:
АдресФото. Зададим ему тип Строка. Обратите внимание: это реквизит формы, а не реквизит объекта, в базу данных он записываться не будет.АдресФото в левую часть — в дерево элементов формы.Чтобы отобразить картинку в поле формы, нам нужно передать туда ее уникальный веб-адрес внутри системы 1С — навигационную ссылку. Для обеспечения максимальной производительности мы напишем контекстно-независимую функцию. Использование директивы &НаСервереБезКонтекста гарантирует, что при вызове функции клиент не будет передавать на сервер и обратно тяжелые данные всей формы.
Проанализируем программный код серверной функции, который необходимо добавить в модуль формы:
&НаСервереБезКонтекста
Функция ПолучитьАдресИзображенияМодели(Знач СсылкаНаМодель)
Если Не ЗначениеЗаполнено(СсылкаНаМодель) Тогда
Возврат "";
КонецЕсли;
// Используем запрос для быстрого получения ссылки на файл без загрузки всего объекта модели в память
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Модели.Картинка КАК СсылкаНаФайл
|ИЗ
| Справочник.МоделиТСиОборудования КАК Модели
|ГДЕ
| Модели.Ссылка = &СсылкаНаМодель";
Запрос.УстановитьПараметр("СсылкаНаМодель", СсылкаНаМодель);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() И ЗначениеЗаполнено(Выборка.СсылкаНаФайл) Тогда
// "Файл" — это имя реквизита с типом ХранилищеЗначения в справочнике "Файлы"
Возврат ПолучитьНавигационнуюСсылку(Выборка.СсылкаНаФайл, "Файл");
КонецЕсли;
Возврат "";
КонецФункции
В этом коде мы с помощью легкого SQL-запроса получаем ссылку на элемент справочника файлов, а затем стандартной функцией платформы ПолучитьНавигационнуюСсылку() формируем внутренний URL-адрес двоичных данных, хранящихся в СУБД. Именно этот адрес понимает наше Поле картинки на форме.
При открытии уже существующего в базе данных элемента оборудования нам необходимо сразу показать картинку его модели. Для этого пропишем вызов нашей функции в стандартном обработчике события формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Заполняем реквизит формы адресом картинки при создании формы
АдресФото = ПолучитьАдресИзображенияМодели(Объект.Модель);
КонецПроцедуры
Теперь решим ключевую задачу: сделаем так, чтобы картинка менялась мгновенно «на лету» при интерактивном выборе модели пользователем. Разберем этот процесс по шагам:
Модель (связанное с реквизитом Объект.Модель).Код обработчика события будет выглядеть следующим образом:
&НаКлиенте
Процедура МодельПриИзменении(Элемент)
// Динамически получаем новый адрес картинки при изменении модели пользователем
АдресФото = ПолучитьАдресИзображенияМодели(Объект.Модель);
КонецПроцедуры
Благодаря этому коду, как только пользователь выберет другую модель, клиентская процедура мгновенно отправит запрос на сервер, передав туда ссылку на новую модель, получит актуальный адрес картинки во временном хранилище СУБД и обновит элемент отображения на экране.
При проектировании систем, активно работающих с графическими файлами и изображениями, важно учитывать вопросы производительности и масштабируемости базы данных. Проанализируем два ключевых совета от экспертов 1С:
РаботаСФайлами. Она берет на себя все рутинные задачи: добавление, хранение, очистку, кэширование изображений и их привязку к любым объектам конфигурации. Настоятельно рекомендуется интегрировать БСП в свои проекты.