Как программно изменить положение элементов (колонок) в дереве управляемой формы 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Розница Торговля и дистрибуция
← На главную

Рассмотрим частую задачу при разработке на платформе 1С:Предприятие: вы программно добавляете новый реквизит и связываете его с элементом формы (например, добавляете новую колонку в уже существующее «Дерево цен» или таблицу значений). По умолчанию, если использовать стандартный метод добавления, новая колонка появится в самом конце таблицы. Проанализируем ситуацию и разберем по шагам, как управлять позиционированием динамически созданных элементов интерфейса.

Разделим понятия: реквизиты и элементы формы

Первое, что необходимо четко усвоить: реквизиты формы не имеют визуального представления и порядка расположения. РеквизитФормы — это исключительно хранилище данных (число, строка, массив и т.д.). Местоположение реквизита в массиве реквизитов не имеет абсолютно никакого значения.

Сдвигать, перемещать и позиционировать мы можем только элементы формы (поля ввода, флажки, колонки таблиц), которые отображаются пользователю. Поэтому наша задача сводится к правильной работе с коллекцией Элементы.

Способ 1: Использование метода Вставить при создании элемента

Многие разработчики по привычке создают элементы методом Добавить(), который автоматически помещает новый объект в конец родительской группы. Однако, если мы посмотрим на возможности платформы, выясним, что метод Вставить() решает нашу задачу уже на этапе инициализации элемента.

Синтаксис метода имеет следующий вид: Элементы.Вставить(<Имя>, <Тип>, <Родитель>, <ЭлементПеред>). Именно четвертый параметр позволяет указать конкретную позицию. Рассмотрим пример кода, в котором мы сразу вставляем новую колонку перед нужным элементом:


// Предполагается, что массив мНовыеРеквизиты уже сформирован и применен через ЭтаФорма.ИзменитьРеквизиты()
ЭлементПередКоторымВставляем = Элементы.Найти("СтараяКолонка");

Если ЭлементПередКоторымВставляем <> Неопределено Тогда
    // Используем Вставить вместо Добавить
    пНовыйЭлемент = Элементы.Вставить("Расш1_Корректор", Тип("ПолеФормы"), Элементы.ДеревоЦен, ЭлементПередКоторымВставляем);
    пНовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
    пНовыйЭлемент.ПутьКДанным = "ДеревоЦен.РеквизитКорректор";
КонецЕсли;

Важный нюанс: при добавлении колонки в дерево или таблицу, родителем должна выступать сама таблица (в нашем случае Элементы.ДеревоЦен). Если вы ошибетесь и укажете в качестве родителя саму форму, элемент не попадет в таблицу, а отобразится как отдельное поле внизу окна.

Способ 2: Использование метода Переместить для существующих элементов

Если элемент формы уже был создан (например, типовым механизмом или сторонним кодом), и нам нужно изменить его визуальное расположение, применим метод Переместить(). Он принимает три параметра: перемещаемый элемент, его нового (или текущего) родителя и элемент, перед которым он должен встать.

Разберем отказоустойчивый пример поиска и перемещения элемента:


ПеремещаемыйЭлемент = Элементы.Найти("Расш1_Корректор");
ЭлементПозиции = Элементы.Найти("КолонкаЦена");

Если ПеремещаемыйЭлемент <> Неопределено И ЭлементПозиции <> Неопределено Тогда
    // Перемещаем нашу колонку так, чтобы она встала ПЕРЕД колонкой "КолонкаЦена"
    Элементы.Переместить(ПеремещаемыйЭлемент, Элементы.ДеревоЦен, ЭлементПозиции);
КонецЕсли;

Обратите внимание: мы используем метод Найти() с обязательной проверкой на Неопределено. Жестко обращаться к динамическим элементам через точку (например, Элементы.Расш1_Корректор) небезопасно, так как при малейшем сбое инициализации элемента такой код вызовет критическую ошибку выполнения и прервет работу пользователя.

Решение проблемы конфликта с типовым кодом: уходим от «костылей»

На практике программисты часто сталкиваются с ситуацией: если добавить программные реквизиты до отработки типовых процедур (например, заполнения дерева при открытии), стандартный код 1С может завершиться с ошибкой, так как он не ожидает появления неизвестных колонок.

Иногда это пытаются решить сложным путем: сохраняют данные своих колонок в таблицу значений, удаляют колонки, дают отработать типовому коду 1С, а затем заново создают реквизиты и восстанавливают данные. Это громоздко и замедляет работу формы.

Посмотрим на современное и правильное решение с использованием Механизма расширений конфигурации:

  1. Не модифицируйте основную процедуру ПриСозданииНаСервере в расширении с помощью директивы &Вместо.
  2. Создайте в расширении перехватчик с директивой &После("ПриСозданииНаСервере").
  3. В этот момент вся типовая логика 1С уже успешно отработает со своим стандартным деревом цен.
  4. Именно в обработчике &После программно добавьте ваш новый реквизит РеквизитКорректор и элемент формы.

Таким образом, мы исключаем конфликт стандартных функций конфигурации с нашими доработками. Нам не придется писать функции для временного сохранения данных в коллекцию, и код станет гораздо чище, прозрачнее и надежнее.

← На главную