При разработке интерфейсов на управляемых формах в 1С:Предприятие 8.3 программисты часто сталкиваются с задачей динамического изменения внешнего вида элементов. Например, требуется установить на кнопку картинку, которая хранится в базе данных (в присоединенных файлах, справочнике номенклатуры или регистре сведений) или генерируется программно "на лету".
Однако при попытке напрямую присвоить созданный объект Картинка свойству кнопки в коде управляемой формы разработчик неизбежно сталкивается с ошибкой: «Ошибка при установке значения атрибута контекста (Картинка) по причине: Недопустимое значение».
В этой статье мы подробно разберем, почему возникает это ограничение платформы, проанализируем синтаксис и рассмотрим четыре проверенных практических способа, которые помогут вам обойти это ограничение и реализовать требуемый функционал в ваших конфигурациях.
Обратимся к официальной документации и Синтакс-Помощнику 1С. Для свойства Картинка элемента формы типа «Кнопка» установлено жесткое системное ограничение. Если заполнение данного свойства происходит программно, то в него может быть передан только объект Картинка определенного вида, а именно:
Попытка передать туда картинку, созданную из двоичных данных, файла на диске или временного хранилища (например, Новый Картинка(ПутьКФайлу)), приводит к вызову исключения. Платформа просто не поддерживает динамическое назначение произвольных бинарных картинок стандартным кнопкам управляемой формы на лету. Тем не менее, эту задачу можно элегантно решить обходными путями.
Это самый популярный, надежный и простой в реализации обходной путь. Вместо стандартного элемента формы «Кнопка» мы будем использовать «Полотно» для вывода изображений, которое заставим вести себя в интерфейсе в точности как обычная кнопка.
Разберем реализацию этого метода по шагам:
АдресИзображенияКнопки. Тип данных для этого реквизита укажем как Строка.Истина (в программном коде это свойство доступно как Элементы.ПолеКартинки.Гиперссылка). Благодаря этому при наведении указателя мыши на картинку курсор будет принимать форму «руки», визуально подсказывая пользователю, что на элемент можно нажать.Пропорционально или Авто, чтобы динамически загружаемые изображения корректно масштабировались под размеры элемента формы.Рассмотрим подробнее пример серверного кода, который помещает картинку в реквизит формы:
&НаСервере
Процедура УстановитьКартинкуНаФорме()
// Вариант А: Если картинка уже хранится в базе данных в реквизите с типом ХранилищеЗначения
СсылкаНаОбъектБД = Справочники.Номенклатура.НайтиПоКоду("000000001");
АдресИзображенияКнопки = ПолучитьНавигационнуюСсылку(СсылкаНаОбъектБД, "ФайлКартинки");
// Вариант Б: Если у нас есть двоичные данные картинки (например, скачали из интернета или сформировали в коде)
// ДвоичныеДанные = ПолучитьДвоичныеДанныеКартинки();
// АдресИзображенияКнопки = ПоместитьВоВременноеХранилище(ДвоичныеДанные, УникальныйИдентификатор);
КонецПроцедуры
Этот метод визуально ничем не отличается для пользователя от обычной кнопки, работает крайне быстро и не вызывает зависаний интерфейса. Для организации загрузки и хранения картинок в базе данных подойдёт готовый шаблон сохранения изображений в ХранилищеЗначения.
Если перед вами стоит задача спроектировать сложный и динамичный плиточный интерфейс (например, графическое меню для рабочего места кассира (РМК), терминала самообслуживания или рабочего стола официанта), то предыдущий метод может оказаться слишком громоздким. В таких случаях идеальным решением будет использование встроенного браузера 1С.
Проанализируем ситуацию: поле HTML-документа позволяет вывести абсолютно любую верстку, поддерживающую современные стандарты стилей CSS и разметки HTML. Мы можем налету сгенерировать красивую сетку кнопок с любыми картинками.
Разберем по шагам алгоритм реализации:
Строка, например, HTMLКодПанели.Base64. Картинку можно вставить прямо в тело тега картинки.Посмотрим на пример формирования такого кода в модуле формы:
&НаСервере
Процедура СформироватьДинамическоеМеню()
// Получаем двоичные данные нашей картинки из базы данных
ДвоичныеДанныеКартинки = Справочники.Номенклатура.НайтиПоКоду("00000001").ПолучитьОбъект().Изображение.Получить();
Если ДвоичныеДанныеКартинки <> Неопределено Тогда
// Кодируем бинарные данные в строку Base64
СтрокаBase64 = ПолучитьСтрокуBase64ИзДвоичныхДанных(ДвоичныеДанныеКартинки);
ФорматКартинки = "image/png"; // Укажите нужный формат (png, jpeg, gif)
// Формируем HTML-код с внедренной картинкой и стилизованной кнопкой
ТекстHTML = "<html><body style='margin:0; padding:0; background-color:#f0f0f0;'>";
ТекстHTML = ТекстHTML + "<div style='display:flex; justify-content:center; align-items:center; height:100vh;'>";
ТекстHTML = ТекстHTML + "<a href='onclick:MyActionButton' id='btn1' style='text-decoration:none; display:inline-block; padding:10px; background:#fff; border:1px solid #ccc; border-radius:5px;'>";
ТекстHTML = ТекстHTML + "<img src='data:" + ФорматКартинки + ";base64," + СтрокаBase64 + "' width='64' height='64' />";
ТекстHTML = ТекстHTML + "<p style='text-align:center; margin:5px 0 0 0; font-family:Arial; font-size:12px;'>Нажми меня</p>";
ТекстHTML = ТекстHTML + "</a></div></body></html>";
HTMLКодПанели = ТекстHTML;
КонецЕсли;
КонецПроцедуры
Для обработки нажатия на такую кнопку мы используем стандартное событие элемента формы ПриНажатии у поля HTML-документа. Программа перехватит переход по навигационной ссылке вида onclick:MyActionButton, отменит стандартное поведение браузера и выполнит необходимый код на встроенном языке 1С.
Рассмотрим сценарий, когда набор картинок, которые могут быть установлены на кнопку, известен заранее и ограничен. Например, кнопка должна менять свой внешний вид в зависимости от статуса документа: «Новый», «В работе», «Проведен», «Отклонен».
В этом случае нам не нужно пытаться загружать файлы из внешних источников на лету. Мы можем использовать штатные механизмы платформы, так как замена картинок из библиотеки разрешена разработчиками 1С программно. Для наполнения библиотеки метаданных можно использовать набор графических ресурсов и иконок платформы 1С.
Для реализации этого подхода выполним следующие действия:
СтатусНовый, СтатусВРаботе, СтатусЗавершен).Картинка кнопки элементы из системной библиотеки картинок.Давайте посмотрим на пример программного кода:
&НаКлиенте
Процедура ОбновитьВидКнопкиПоСтатусу(ТекущийСтатус)
// Программное изменение картинки кнопки разрешено, если картинка берется из библиотеки
Если ТекущийСтатус = ПредопределенноеЗначение("Перечисление.СтатусыЗаказов.Новый") Тогда
Элементы.КнопкаДействия.Картинка = БиблиотекаКартинок.СтатусНовый;
Элементы.КнопкаДействия.Заголовок = "Запустить в работу";
ИначеЕсли ТекущийСтатус = ПредопределенноеЗначение("Перечисление.СтатусыЗаказов.ВРаботе") Тогда
Элементы.КнопкаДействия.Картинка = БиблиотекаКартинок.СтатусВРаботе;
Элементы.КнопкаДействия.Заголовок = "Завершить работу";
Иначе
Элементы.КнопкаДействия.Картинка = БиблиотекаКартинок.СтатусЗавершен;
Элементы.КнопкаДействия.Заголовок = "Закрыть заказ";
КонецЕсли;
КонецПроцедуры
Этот способ является максимально быстрым, стабильным и "чистым" с точки зрения архитектуры платформы, поскольку не требует задействования временных хранилищ и веб-технологий.
Если вариантов отображения кнопки всего два или три, и при этом они статичны, можно применить простой трюк с видимостью элементов. Вместо того чтобы мучаться с программным переопределением свойств одной кнопки, мы создаем в конфигураторе несколько физически разных кнопок.
Каждой кнопке мы жестко и статично задаем свою картинку из библиотеки или файлов еще на этапе разработки формы. Затем мы объединяем эти кнопки в одну группу (без отображения границ) и управляем их отображением.
Проанализируем пример кода, управляющего видимостью элементов на форме:
&НаСервере
Процедура УправлениеКнопкамиНаСервере(ЗначениеПереключателя)
// В зависимости от логики делаем видимой только одну нужную кнопку
Элементы.КнопкаВариантА.Видимость = (ЗначениеПереключателя = 1);
Элементы.КнопкаВариантБ.Видимость = (ЗначениеПереключателя = 2);
Элементы.КнопкаВариантВ.Видимость = (ЗначениеПереключателя = 3);
КонецПроцедуры
Этот метод чрезвычайно прост в отладке, не создает никакой нагрузки на серверную часть и моментально отрабатывает на стороне тонкого клиента.
Мы подробно разобрали системное ограничение управляемых форм 1С:Предприятие 8.3 на программную установку произвольных картинок для кнопок и изучили методы его обхода. Выбор конкретного решения зависит от вашей архитектурной задачи: