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