Почему в динамическом списке расширения пропадают колонки или стандартные команды?

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

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

  1. Если в свойствах списка указана Основная таблица, то пропадают все добавленные колонки (остается только стандартная картинка, флажок или ссылка), хотя запрос написан корректно.
  2. Если убрать свойство Основная таблица, колонки появляются и отображаются данные, но с формы исчезают стандартные команды: "Создать", "Скопировать", "Удалить", "Пометить на удаление".

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

Природа конфликта: Основная таблица и Расширение

Для начала давайте проанализируем особенности динамических списков и зачем вообще нужно свойство ОсновнаяТаблица.

Когда мы указываем основную таблицу (например, Справочник.КонтактныеЛицаПартнеров), платформа 1С пытается автоматически обеспечить стандартное поведение интерфейса для этого объекта:

Почему исчезают колонки?
В контексте расширения конфигурации метаданные заимствованного объекта могут быть не полностью инициализированы в момент построения формы конструктором. Если в вашем произвольном запросе используются поля, к которым у платформы возникают вопросы по правам доступа (или псевдонимы полей запроса не совпадают с именами реквизитов, ожидаемыми "Основной таблицей"), платформа в целях безопасности перестраховывается. Она скрывает поля, которые не может однозначно сопоставить с правами RLS, оставляя только гарантированно безопасные (например, ссылку).

Почему исчезают команды?
Если мы очищаем свойство ОсновнаяТаблица, мы фактически говорим платформе: "Это просто произвольный набор данных, не привязанный к конкретному объекту базы данных". Платформа перестает понимать, что именно нужно "Создавать" или "Удалять" при нажатии кнопок. Поэтому стандартные кнопки исчезают, так как контекст объекта потерян.

Решение 1: Программная настройка списка (Рекомендуемое)

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

В этом подходе мы оставляем в конфигураторе настройки списка "как есть" (или даже пустыми), а в момент запуска формы принудительно устанавливаем нужные параметры.

Рассмотрим алгоритм действий:

  1. В визуальном редакторе формы убедитесь, что у вашего списка (допустим, он называется Список) свойство Произвольный запрос установлено в Истина.
  2. Свойство Основная таблица в палитре свойств можно оставить пустым, чтобы не вызывать конфликтов при сохранении расширения.
  3. Перейдем в модуль формы и создадим обработчик события ПриСозданииНаСервере.

Напишем код, который явно задаст текст запроса и основную таблицу:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	// Формируем текст запроса. 
	// Лучше всего скопировать его из консоли запросов или конструктора.
	ТекстЗапросаСписка = 
		"ВЫБРАТЬ
		|	КонтактныеЛицаПартнеров.Ссылка КАК Ссылка,
		|	КонтактныеЛицаПартнеров.ПометкаУдаления КАК ПометкаУдаления,
		|	КонтактныеЛицаПартнеров.Наименование КАК Наименование,
		|	КонтактныеЛицаПартнеров.Владелец КАК Владелец,
		|	ИзменениеСостоянийРаботыСЛидами.Состояние КАК Состояние
		|ИЗ
		|	Справочник.КонтактныеЛицаПартнеров КАК КонтактныеЛицаПартнеров
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИзменениеСостоянийРаботыСЛидами.СрезПоследних КАК ИзменениеСостоянийРаботыСЛидами
		|		ПО КонтактныеЛицаПартнеров.Ссылка = ИзменениеСостоянийРаботыСЛидами.Лид";

	// Устанавливаем текст запроса динамическому списку
	Список.ТекстЗапроса = ТекстЗапросаСписка;
	
	// ВАЖНО: Устанавливаем основную таблицу программно.
	// Именно этот шаг возвращает стандартные команды (Создать, Удалить),
	// но будучи выполненным в коде, он обычно не ломает видимость колонок.
	Список.ОсновнаяТаблица = "Справочник.КонтактныеЛицаПартнеров";
	
	// Дополнительно можно включить динамическое считывание, если список большой
	Список.ДинамическоеСчитываниеДанных = Истина;

КонецПроцедуры

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

Решение 2: Ручное добавление команд (Без основной таблицы)

Если по какой-то причине установка основной таблицы все равно скрывает колонки (например, из-за сложных ограничений RLS на уровне записи), можно пойти другим путем: не указывать основную таблицу вовсе, но вернуть команды вручную.

Разберем этот метод:

  1. В свойствах реквизита Список очистите поле Основная таблица. Убедитесь, что колонки отображаются корректно в режиме Предприятия.
  2. Перейдите на вкладку Команды в редакторе формы.
  3. В разделе Стандартные команды (или Глобальные команды) найдите команды, относящиеся к нужному справочнику (Создать, Скопировать и т.д.). Однако, так как основная таблица не задана, они могут быть недоступны для автоматической привязки.
  4. Более надежный вариант: перетащить стандартные команды из источника данных.
    • Если это не работает, создайте свои собственные команды формы: СоздатьЛицо, УдалитьЛицо.

Пример кода для пользовательских команд:


&НаКлиенте
Процедура СоздатьЛицо(Команда)
	// Открываем форму создания нового элемента
	ОткрытьФорму("Справочник.КонтактныеЛицаПартнеров.ФормаОбъекта");
КонецПроцедуры

&НаКлиенте
Процедура УдалитьЛицо(Команда)
	// Получаем текущие данные строки
	ТекущиеДанные = Элементы.Список.ТекущиеДанные;
	If ТекущиеДанные <> Неопределено Тогда
		УдалитьЭлементНаСервере(ТекущиеДанные.Ссылка);
	КонецЕсли;
КонецПроцедуры

Этот метод более трудоемкий, так как требует ручной реализации стандартного функционала, поэтому Решение 1 является приоритетным.

Важные нюансы запроса в Динамическом списке

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


ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ИзменениеСостоянийРаботыСЛидами.СрезПоследних КАК ИзменениеСостоянийРаботыСЛидами

Есть распространенное заблуждение, что использовать виртуальные таблицы (СрезПоследних, Остатки) в динамических списках нельзя. Это не совсем так. Использовать их можно, но с оговорками:

Проверка псевдонимов полей

Еще одна причина, по которой колонки могут исчезать при установленной ОсновнойТаблице — несовпадение имен полей.

Если в ОсновнойТаблице есть реквизит Ответственный, а в вашем запросе вы выбираете его как:

... ВЫБРАТЬ Справочник.Менеджер КАК Ответственный ...

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

Подведем итог: Для решения проблемы в расширении лучше всего использовать программную установку текста запроса и свойства ОсновнаяТаблица в событии ПриСозданииНаСервере. Это гарантирует корректную работу и колонок, и командной панели.

← На главную