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