Разработка интерфейсов на обычных формах в «1С:Предприятии 8» часто сопряжена с трудностями при настройке динамического поведения элементов. Типичный сценарий: на форме расположены левая панель, правая табличная часть и разделитель (сплиттер) между ними. При изменении настроек видимости (например, с помощью флажков) необходимо, чтобы оставшийся видимым элемент растягивался на всю ширину формы, а при возврате к исходному состоянию — элементы снова корректно делили экран и управлялись разделителем.
В этой статье мы подробно разберем, почему стандартное скрытие элементов ломает верстку, как правильно управлять привязками программно, и рассмотрим альтернативные, более надежные методы проектирования таких интерфейсов.
Основная проблема, с которой сталкиваются разработчики при программном скрытии разделителя и изменении видимости соседних элементов, заключается в логике работы движка обычных форм 1С. Когда мы устанавливаем свойство Видимость = Ложь для разделителя, он визуально исчезает с экрана. Однако он не исключается из цепочки привязок формы.
Если правая граница левой панели привязана к левой границе разделителя, то даже в невидимом состоянии разделитель продолжает «удерживать» эту границу. В результате панель не может растянуться до правого края формы и остается зажатой на своей половине. Чтобы заставить элементы вести себя корректно, нам необходимо программно перестроить привязки или изменить логику компоновки интерфейса.
Рассмотрим подробнее три надежных способа решения этой задачи.
Если вы хотите решить задачу «в лоб», управляя положением элементов на лету, необходимо строго соблюдать последовательность действий. Платформа 1С жестко фиксирует расстояния при установке привязок. Если сначала привязать границы, а затем менять размеры, интерфейс отобразится некорректно.
Разберем по шагам правильный алгоритм перестройки интерфейса:
Лево и Ширина) для текущего состояния.Посмотрим на пример программной реализации этого алгоритма. Обратите внимание на синтаксис метода УстановитьПривязку(). Чтобы привязать границу элемента к краю самой формы, второй параметр метода (первый элемент привязки) нужно оставлять пустым или передавать в него Неопределено.
Процедура УстановитьПривязки()
ШиринаРабочейОбласти = Ширина - 16; // Вычисляем доступную ширину с учетом отступов
Если ФлажокD = Истина И ФлажокQ = Ложь Тогда
// 1. Скрываем ненужное
ЭлементыФормы.Разделитель1.Видимость = Ложь;
ЭлементыФормы.ТабличноеПоле1.Видимость = Ложь;
ЭлементыФормы.Панель1.Видимость = Истина;
// 2. Сбрасываем старые привязки правой границы панели
ЭлементыФормы.Панель1.УстановитьПривязку(ГраницаЭлементаУправления.Право);
// 3. Задаем панели максимальную ширину
ЭлементыФормы.Панель1.Ширина = ШиринаРабочейОбласти;
// 4. Привязываем правую границу панели к правой границе самой формы
ЭлементыФормы.Панель1.УстановитьПривязку(ГраницаЭлементаУправления.Право, , ГраницаЭлементаУправления.Право);
ИначеЕсли ФлажокD = Ложь И ФлажокQ = Истина Тогда
// Скрываем панель и разделитель, показываем только таблицу
ЭлементыФормы.Разделитель1.Видимость = Ложь;
ЭлементыФормы.Панель1.Видимость = Ложь;
ЭлементыФормы.ТабличноеПоле1.Видимость = Истина;
// Сбрасываем привязку левой границы таблицы
ЭлементыФормы.ТабличноеПоле1.УстановитьПривязку(ГраницаЭлементаУправления.Лево);
// Растягиваем таблицу от левого края формы
ЭлементыФормы.ТабличноеПоле1.Лево = 8;
ЭлементыФормы.ТабличноеПоле1.Ширина = ШиринаРабочейОбласти;
// Привязываем левую границу таблицы к левому краю формы
ЭлементыФормы.ТабличноеПоле1.УстановитьПривязку(ГраницаЭлементаУправления.Лево, , ГраницаЭлементаУправления.Лево);
ИначеЕсли ФлажокD = Истина И ФлажокQ = Истина Тогда
// Возвращаем стандартную схему с разделителем
ЭлементыФормы.Разделитель1.Видимость = Истина;
ЭлементыФормы.Панель1.Видимость = Истина;
ЭлементыФормы.ТабличноеПоле1.Видимость = Истина;
// Вычисляем новые пропорциональные размеры
ПоловинаШирины = Цел(ШиринаРабочейОбласти / 2);
ЭлементыФормы.Панель1.Ширина = ПоловинаШирины - 4;
ЭлементыФормы.Разделитель1.Лево = ЭлементыФормы.Панель1.Лево + ЭлементыФормы.Панель1.Ширина;
ЭлементыФормы.ТабличноеПоле1.Лево = ЭлементыФормы.Разделитель1.Лево + ЭлементыФормы.Разделитель1.Ширина;
ЭлементыФормы.ТабличноеПоле1.Ширина = ШиринаРабочейОбласти - (ЭлементыФормы.Панель1.Ширина + ЭлементыФормы.Разделитель1.Ширина);
// Привязываем панель к левой стороне разделителя
ЭлементыФормы.Панель1.УстановитьПривязку(ГраницаЭлементаУправления.Право, ЭлементыФормы.Разделитель1, ГраницаЭлементаУправления.Лево);
// Привязываем таблицу к правой стороне разделителя
ЭлементыФормы.ТабличноеПоле1.УстановитьПривязку(GradicaElementaUpravleniya.Лево, ЭлементыФормы.Разделитель1, ГраницаЭлементаУправления.Право);
КонецЕсли;
КонецПроцедуры
Важный технический нюанс: Иногда после программного изменения привязок платформа не перерисовывает элементы мгновенно, из-за чего они визуально кажутся застывшими. Чтобы принудительно заставить движок обычных форм пересчитать привязки и перерисовать интерфейс, примените проверенный трюк в конце процедуры управления видимостью — искусственное микро-изменение размеров формы на 1 пиксель:
ЭтаФорма.Ширина = ЭтаФорма.Ширина + 1;
ЭтаФорма.Ширина = ЭтаФорma.Ширина - 1;
Для решения подобных задач разработчики платформы предусмотрели встроенный инструмент — механизм свертки элементов управления. Если правильно связать элементы «паровозиком» в конфигураторе, то при программном сворачивании панели и разделителя соседняя таблица будет автоматически занимать все освободившееся пространство без необходимости ручного пересчета пикселей.
Проанализируем настройку в конфигураторе:
Панели1 привязку правой границы к левой границе Разделителя1.ТабличногоПоля1 привязку левой границы к правой границе Разделителя1.Панели1 в палитре свойств укажите свойство РежимСверткиЭлементаУправления в значение Лево.Разделителя1 укажите аналогичный режим свертки — Лево.При такой настройке код переключения видимости существенно упрощается. Нам не нужно вручную менять координаты и заново устанавливать привязки через УстановитьПривязку(). Достаточно использовать следующее программное решение:
Если ФлажокD = Ложь И ФлажокQ = Истина Тогда
// Сворачиваем панель и разделитель влево. Табличное поле автоматически займет всю форму.
ЭлементыФормы.Панель1.Свертка = РежимСверткиЭлементаУправления.Лево;
ЭлементыФормы.Разделитель1.Свертка = РежимСверткиЭлементаУправления.Лево;
ИначеЕсли ФлажокD = Истина И ФлажокQ = Ложь Тогда
// В этом случае скрываем таблицу стандартным способом сжатия вправо
ЭлементыФормы.ТабличноеПоле1.Свертка = РежимСверткиЭлементаУправления.Право;
ЭлементыФормы.Разделитель1.Свертка = РежимСверткиЭлементаУправления.Право;
Иначе
// Возвращаем все элементы в исходное развернутое состояние
ЭлементыФормы.Панель1.Свертка = РежимСверткиЭлементаУправления.Нет;
ЭлементыФормы.Разделитель1.Свертка = РежимСверткиЭлементаУправления.Нет;
ЭлементыФормы.ТабличноеПоле1.Свертка = РежимСверткиЭлементаУправления.Нет;
КонецЕсли;
На практике динамические привязки в сложных обычных формах 1С могут вести себя непредсказуемо, особенно если пользователь вручную изменяет размеры окна программы, перетаскивая границы экрана или меняя разрешение монитора. Чтобы полностью обезопасить себя от «съезжающих» элементов и не писать сложный код позиционирования, применим изящное проектное решение — многостраничную панель со скрытыми вкладками.
Суть метода заключается в том, чтобы отказаться от динамического перемещения элементов по одной форме. Вместо этого мы создаем три разные статические сцены и переключаемся между ними.
Выполним следующие шаги по настройке в конфигураторе:
Панель (назовем ее ОсновнаяПанель) и растянем ее на всю рабочую область формы. Зададим ей привязки ко всем четырем сторонам формы (чтобы она масштабировалась при изменении размеров окна).ОтображениеЗакладок в значение Не отображать. Панель станет визуально бесшовной, без закладок сверху.Панель1. Растягиваем ее на всю ширину страницы панели. Ее привязки устанавливаем стандартно «Граница формы - Граница формы» (лево-право-верх-низ).ТабличноеПоле1. Также растягиваем его на всю ширину и привязываем ко всем краям страницы.Теперь весь программный код управления логикой отображения при изменении флажков сводится к лаконичному переключению активной страницы панели:
Процедура ПриИзмененииФлажков()
Если ФлажокD = Истина И ФлажокQ = Ложь Тогда
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = ЭлементыФормы.ОсновнаяПанель.Страницы.Страница_D;
ИначеЕсли ФлажокD = Ложь И ФлажокQ = Истина Тогда
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = ЭлементыФормы.ОсновнаяПанель.Страницы.Страница_Q;
ИначеЕсли ФлажокD = Истина И ФлажокQ = Истина Тогда
ЭлементыФормы.ОсновнаяПанель.ТекущаяСтраница = ЭлементыФормы.ОсновнаяПанель.Страницы.Страница_DQ;
КонецЕсли;
КонецПроцедуры
Преимущества данного подхода очевидны: во-первых, мы полностью исключаем громоздкие математические расчеты координат в пикселях. Во-вторых, этот подход на 100% стабилен и гарантирует, что привязки элементов не «слетят» ни при каких обстоятельствах. В-третьих, поддерживать и дорабатывать дизайн каждой страницы по отдельности в конфигураторе в будущем будет намного проще, чем разбираться в формулах программной расстановки элементов.
Таким образом, мы рассмотрели различные варианты реализации динамического интерфейса. Выберите оптимальный метод исходя из сложности вашей формы: для простых интерфейсов отлично подойдет механизм встроенной свертки (Способ 2), а для тяжелых, насыщенных реквизитами форм идеальным выбором станет использование многостраничной панели со скрытыми закладками (Способ 3).