В процессе перехода с обычных форм на управляемые разработчики часто сталкиваются с отсутствием привычного свойства «Распределять по страницам». В старой архитектуре это свойство позволяло одной и той же таблице (или другому элементу управления) физически находиться на разных вкладках панели, что было удобно для создания интерфейсов с единым контекстом данных. В управляемых формах концепция изменилась: один элемент может иметь только одного «родителя» в иерархии формы. Однако потребность в таком поведении осталась, особенно когда нужно переключаться между разными разрезами одних и тех же данных (например, вариантами расчета цен). Рассмотрим подробнее, какими способами можно имитировать это поведение, сохраняя производительность и удобство интерфейса.
Прежде чем мы разберем решения, выясним причину, почему разработчики 1С отказались от этого свойства. В управляемом приложении форма представляет собой декларативное описание, которое передается с сервера на клиент. На клиенте строится дерево элементов. Если бы один элемент принадлежал разным страницам, возникла бы коллизия состояний и иерархии. Поэтому мы не можем просто поставить «галочку» в свойствах, но можем использовать механизмы программного управления интерфейсом.
Проанализируем самый прямой аналог — физическое перемещение таблицы на ту страницу, которую пользователь выбрал в данный момент. Этот метод хорош тем, что мы используем один и тот же объект ТаблицаФормы, сохраняя все настройки пользователя (ширину колонок, положение курсора и т.д.).
Рассмотрим алгоритм реализации по шагам:
ГруппаСтраницыВарианты).ПриСменеСтраницы для группы страниц.Элементы.Переместить().Посмотрим на пример кода:
&НаКлиенте
Процедура ГруппаСтраницыВариантыПриСменеСтраницы(Элемент, ТекущаяСтраница)
// Перемещаем таблицу в активную страницу
Элементы.Переместить(Элементы.ТаблицаРасчетов, ТекущаяСтраница);
// Если данные таблицы зависят от страницы, устанавливаем фильтр
ТекущийВариант = ТекущаяСтраница.Имя; // Предположим, имя страницы соответствует ключу варианта
УстановитьФильтрТаблицы(ТекущийВариант);
КонецПроцедуры
Этот способ позволяет избежать дублирования элементов и не перегружает форму. Однако помните, что при большом количестве данных в таблице визуальное «перепрыгивание» может быть заметно пользователю.
Если нам нужно, чтобы таблицы выглядели как независимые сущности на каждой вкладке, но при этом смотрели в один источник данных (одну табличную часть объекта), мы можем применить механизм динамического создания элементов формы. Это более гибкий подход, который позволяет каждой вкладке иметь свой «взгляд» на данные.
Разберем ситуацию: у нас есть общая таблица в данных, но на каждой странице мы хотим видеть только строки, относящиеся к конкретному варианту. Для этого используется свойство ОтборСтрок.
Пример программного создания таблицы в процедуре ПриСозданииНаСервере:
&НаСервере
Процедура СоздатьТаблицыНаСтраницах()
Для Каждого Вариант Из СписокВариантов Цикл
// 1. Создаем страницу
ИмяСтраницы = "Страница_" + Вариант.Ключ;
НоваяСтраница = Элементы.Добавить(ИмяСтраницы, Тип("ГруппаФормы"), Элементы.ГруппаВарианты);
НоваяСтраница.Вид = ВидГруппыФормы.Страница;
НоваяСтраница.Заголовок = Вариант.Представление;
// 2. Добавляем таблицу на эту страницу
ИмяТаблицы = "Таблица_" + Вариант.Ключ;
НоваяТаблица = Элементы.Добавить(ИмяТаблицы, Тип("ТаблицаФормы"), НоваяСтраница);
НоваяТаблица.ПутьКДанным = "Объект.Товары"; // Все таблицы смотрят в одну ТЧ
// 3. Устанавливаем ФИКСИРОВАННЫЙ отбор для этой таблицы
Отбор = Новый ФиксированнаяСтруктура("КлючВарианта", Вариант.Ключ);
НоваяТаблица.ОтборСтрок = Отбор;
// 4. Добавляем колонки (программно)
НоваяКолонка = Элементы.Добавить("КолонкаНоменклатура_" + Вариант.Ключ, Тип("ПолеФормы"), НоваяТаблица);
НоваяКолонка.Вид = ВидПоляФормы.ПолеВвода;
НоваяКолонка.ПутьКДанным = "Объект.Товары.Номенклатура";
КонецЦикла;
КонецПроцедуры
Важный нюанс: Использование ОтборСтрок позволяет отображать в каждой таблице только нужные данные, при этом физически данные остаются в одной коллекции Объект.Товары. Это значительно упрощает сохранение данных в базу.
Проанализируем ситуацию, когда страниц становится слишком много (более 10). Вкладки в этом случае начинают располагаться в несколько рядов, что сильно уменьшает рабочую область. Выясним, как сделать интерфейс более современным.
Вместо стандартной группы страниц мы можем использовать ПолеФормы с видом ПолеПереключателя и установленным режимом Тумблер. Визуально это выглядит как горизонтальный ряд кнопок.
ПолеПереключателя в верхней части формы.Пример настройки отбора:
&НаКлиенте
Процедура ПереключательВариантовПриИзменении(Элемент)
ЭлементОтбора = Новый Структура("ВариантРасчета", Объект.ТекущийВариант);
// Применяем отбор к единственной таблице на форме
Элементы.ТаблицаДанных.ОтборСтрок = Новый ФиксированнаяСтруктура(ЭлементОтбора);
КонецПроцедуры
Этот подход считается наиболее производительным, так как форма остается «легкой» — на ней минимум элементов управления, а меняются только параметры фильтрации.
Рассмотрим подробнее, какой метод выбрать в зависимости от условий задачи:
Элементы.Переместить(). Это проще всего в реализации и поддержке.Элементы.ИмяКолонки.Видимость = Ложь/Истина.Выясним причину, по которой не стоит злоупотреблять количеством таблиц на форме. В управляемом приложении каждое поле и каждая колонка — это объекты, состояние которых синхронизируется между сервером и клиентом. Если вы создадите 20 страниц и на каждой разместите таблицу с 50 колонками, объем XML-пакета, передаваемого при каждом серверном вызове, может достичь нескольких мегабайт. Это приведет к значительным задержкам (интерфейс будет «тормозить»).
Совет: Если вам необходимо реализовать сложную логику с множеством вкладок, рассмотрите возможность использования Вертикальной навигации. Это паттерн, используемый в интерфейсе «Такси», где слева располагается список или дерево (навигатор), а справа — область данных. При активации строки в навигаторе вы просто обновляете содержимое одной-единственной таблицы справа.
Если вы решили использовать одну таблицу, которая фильтруется под разные «вкладки», вы можете столкнуться с необходимостью выделять данные цветом или шрифтом в зависимости от контекста. Для этого используйте УсловноеОформление формы.
Пример настройки оформления:
ЭлементОформления = УсловноеОформление.Элементы.Добавить();
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветФона", ЦветаСтиля.ЦветФонаВыделения);
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ТаблицаТоварыЦена");
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Объект.Товары.ВариантИзменен");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборОформления.ПравоеЗначение = Истина;
Такой подход позволяет сделать работу пользователя с единой таблицей максимально комфортной, создавая иллюзию работы с разными специализированными инструментами на каждой «виртуальной» странице.
Подводя итог, можно сказать, что хотя прямой замены свойству РаспределятьПоСтраницам в 1С 8.3 не существует, разработчик обладает мощным инструментарием для имитации этого поведения. Главное — соблюдать баланс между удобством пользователя и производительностью системы, отдавая предпочтение методам с программной фильтрацией одной таблицы (ОтборСтрок), нежели созданию десятков одинаковых элементов управления.