Рассмотрим частую задачу при разработке на платформе 1С:Предприятие: вы программно добавляете новый реквизит и связываете его с элементом формы (например, добавляете новую колонку в уже существующее «Дерево цен» или таблицу значений). По умолчанию, если использовать стандартный метод добавления, новая колонка появится в самом конце таблицы. Проанализируем ситуацию и разберем по шагам, как управлять позиционированием динамически созданных элементов интерфейса.
Первое, что необходимо четко усвоить: реквизиты формы не имеют визуального представления и порядка расположения. РеквизитФормы — это исключительно хранилище данных (число, строка, массив и т.д.). Местоположение реквизита в массиве реквизитов не имеет абсолютно никакого значения.
Сдвигать, перемещать и позиционировать мы можем только элементы формы (поля ввода, флажки, колонки таблиц), которые отображаются пользователю. Поэтому наша задача сводится к правильной работе с коллекцией Элементы.
Многие разработчики по привычке создают элементы методом Добавить(), который автоматически помещает новый объект в конец родительской группы. Однако, если мы посмотрим на возможности платформы, выясним, что метод Вставить() решает нашу задачу уже на этапе инициализации элемента.
Синтаксис метода имеет следующий вид: Элементы.Вставить(<Имя>, <Тип>, <Родитель>, <ЭлементПеред>). Именно четвертый параметр позволяет указать конкретную позицию. Рассмотрим пример кода, в котором мы сразу вставляем новую колонку перед нужным элементом:
// Предполагается, что массив мНовыеРеквизиты уже сформирован и применен через ЭтаФорма.ИзменитьРеквизиты()
ЭлементПередКоторымВставляем = Элементы.Найти("СтараяКолонка");
Если ЭлементПередКоторымВставляем <> Неопределено Тогда
// Используем Вставить вместо Добавить
пНовыйЭлемент = Элементы.Вставить("Расш1_Корректор", Тип("ПолеФормы"), Элементы.ДеревоЦен, ЭлементПередКоторымВставляем);
пНовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
пНовыйЭлемент.ПутьКДанным = "ДеревоЦен.РеквизитКорректор";
КонецЕсли;
Важный нюанс: при добавлении колонки в дерево или таблицу, родителем должна выступать сама таблица (в нашем случае Элементы.ДеревоЦен). Если вы ошибетесь и укажете в качестве родителя саму форму, элемент не попадет в таблицу, а отобразится как отдельное поле внизу окна.
Если элемент формы уже был создан (например, типовым механизмом или сторонним кодом), и нам нужно изменить его визуальное расположение, применим метод Переместить(). Он принимает три параметра: перемещаемый элемент, его нового (или текущего) родителя и элемент, перед которым он должен встать.
Разберем отказоустойчивый пример поиска и перемещения элемента:
ПеремещаемыйЭлемент = Элементы.Найти("Расш1_Корректор");
ЭлементПозиции = Элементы.Найти("КолонкаЦена");
Если ПеремещаемыйЭлемент <> Неопределено И ЭлементПозиции <> Неопределено Тогда
// Перемещаем нашу колонку так, чтобы она встала ПЕРЕД колонкой "КолонкаЦена"
Элементы.Переместить(ПеремещаемыйЭлемент, Элементы.ДеревоЦен, ЭлементПозиции);
КонецЕсли;
Обратите внимание: мы используем метод Найти() с обязательной проверкой на Неопределено. Жестко обращаться к динамическим элементам через точку (например, Элементы.Расш1_Корректор) небезопасно, так как при малейшем сбое инициализации элемента такой код вызовет критическую ошибку выполнения и прервет работу пользователя.
На практике программисты часто сталкиваются с ситуацией: если добавить программные реквизиты до отработки типовых процедур (например, заполнения дерева при открытии), стандартный код 1С может завершиться с ошибкой, так как он не ожидает появления неизвестных колонок.
Иногда это пытаются решить сложным путем: сохраняют данные своих колонок в таблицу значений, удаляют колонки, дают отработать типовому коду 1С, а затем заново создают реквизиты и восстанавливают данные. Это громоздко и замедляет работу формы.
Посмотрим на современное и правильное решение с использованием Механизма расширений конфигурации:
ПриСозданииНаСервере в расширении с помощью директивы &Вместо.&После("ПриСозданииНаСервере").&После программно добавьте ваш новый реквизит РеквизитКорректор и элемент формы.Таким образом, мы исключаем конфликт стандартных функций конфигурации с нашими доработками. Нам не придется писать функции для временного сохранения данных в коллекцию, и код станет гораздо чище, прозрачнее и надежнее.