Как реализовать редактирование поля и установку флажков в динамическом списке 1С без открытия формы элемента?

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

Разработчики при переходе на управляемые формы 1С часто сталкиваются со следующей задачей: в форме списка (например, справочника «Номенклатура» или «Контрагенты») выводится динамический список, в котором присутствует булево поле — например, «Проверено», «Заблокирован» или просто колонка для пометки выбора. Естественное желание пользователя — кликать по этому полю прямо в списке и мгновенно переключать флажок (Истина/Ложь) без необходимости открывать громоздкую форму элемента, вносить изменения там, нажимать «Записать и закрыть» и ждать обновления списка.

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

Почему событие «ПриИзменении» не работает в динамическом списке напрямую?

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

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

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

Способ №1. Прямое изменение реквизита в базе данных при двойном клике (событие «Выбор»)

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

Для реализации этого поведения мы задействуем событие Выбор таблицы управляемой формы, в которую выведен наш динамический список. Посмотрим на алгоритм реализации:

  1. Открываем форму списка, выбираем элемент формы (таблицу динамического списка) и находим в свойствах событие Выбор. Создаем обработчик на клиенте.
  2. В обработчике отменяем стандартное поведение платформы (открытие формы элемента) с помощью параметра СтандартнаяОбработка = Ложь.
  3. Определяем, по какой именно колонке кликнул пользователь. Изменение флага должно происходить только при клике на колонку «Проверка».
  4. Вызываем серверную процедуру для быстрого изменения значения в базе данных.
  5. Обновляем динамический список на клиенте.

Давайте разберем пример программного кода, реализующий эту схему:


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

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

Теперь напишем серверную часть, которая будет выполняться без контекста формы (для максимального ускорения работы) или с контекстом, в зависимости от требований:


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

Важное примечание: Чтобы список мгновенно перечитал измененные данные, на клиенте после вызова сервера мы можем вызвать метод Элементы.Список.Обновить(), однако платформа зачастую делает это автоматически при вызове метода ОбновитьОтображениеДанных().

Способ №2. Визуальная пометка элементов в списке без изменения данных в БД (Режим подбора)

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

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

Разберем этот способ по шагам:

Шаг 1. Настройка динамического списка

Переведем динамический список в режим произвольного запроса и добавим в текст запроса искусственное поле «Пометка»:


ВЫБРАТЬ
    СправочникНоменклатура.Ссылка КАК Ссылка,
    СправочникНоменклатура.Код КАК Код,
    СправочникНоменклатура.Наименование КАК Наименование,
    ВЫБОР
        КОГДА СправочникНоменклатура.Ссылка В (&МассивОтмеченных) ТОГДА
            ИСТИНА
        ИНАЧЕ
            ЛОЖЬ
    КОНЕЦ КАК Пометка
ИЗ
    Справочник.Номенклатура КАК СправочникНоменклатура

Шаг 2. Инициализация параметров на форме

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


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартноеОформление)
    
    // Инициализируем пустой массив отмеченных элементов
    МассивОтмеченных = Новый Массив;
    
    // Устанавливаем параметр в динамический список
    Список.Параметры.УстановитьЗначениеПараметра("МассивОтмеченных", МассивОтмеченных);
    
КонецПроцедуры

Шаг 3. Обработка клика пользователя

Снова обратимся к событию таблицы списка Выбор (или ПриАктивизацииЯчейки для имитации нажатия в один клик). Наша задача — поймать клик по колонке «Пометка», оперативно добавить или удалить ссылку из массива отмеченных, передать этот массив обратно в параметры списка и обновить его.


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    
    Если Поле.Имя = "Пометка" Тогда
        
        СтандартнаяОбработка = Ложь;
        
        // Передаем управление серверному методу для обработки коллекции отмеченных элементов
        ОбработатьПометкуНаСервере(ВыбраннаяСтрока);
        
    КонецЕсли;

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

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

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

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

Оптимизация: Использование картинок для красивого визуального отображения флажков

Чтобы сделать интерфейс программы максимально удобным и профессиональным, мы можем отказаться от стандартного текстового отображения «Да» и «Нет» для булевого поля «Пометка». Разберем, как вывести настоящие графические флажки:

  1. В свойствах поля формы «Пометка» (которое выведено в таблицу динамического списка) установим свойство Вид в значение Поле картинки.
  2. Зададим свойство Картинка значений, выбрав стандартную библиотеку картинок БиблиотекаКартинок.СостояниеФлажка (или добавив свою собственную коллекцию картинок, где первая картинка — пустой квадрат, а вторая — квадрат с галочкой).
  3. Установим свойство Гиперссылка ячейки в значение Истина. Это обеспечит изменение курсора на «руку» при наведении на ячейку флажка, подсказывая пользователю, что по элементу можно кликнуть.

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

← На главную