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

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

В интерфейсах «Обычные формы» (ОФ) в 1С разработчики часто сталкиваются с задачей повышения удобства работы пользователей при редактировании булевых реквизитов непосредственно в списках. Стандартное поведение платформы при редактировании данных «в списке» требует от пользователя двойного клика мыши: первый клик переводит строку или ячейку в режим редактирования, а второй — меняет состояние флажка. Если же у справочника в метаданных установлено свойство редактирования «в диалоге», то быстро изменить значение булева реквизита в списке становится еще сложнее.

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

Причина возникновения проблемы

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


Способ 1. Динамическое переключение способа редактирования списка

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

Для реализации этого метода нам необходимо выполнить предварительную настройку свойств объектов в конфигураторе:

  1. Откройте свойства справочника и установите режим редактирования в значение Обеими способами.
  2. В форме списка выберите колонку табличного поля (в нашем примере это НеВыгружать). В палитре свойств колонки укажите:
    • Данные — оставьте это поле пустым.
    • ДанныеФлажка — укажите имя реквизита (НеВыгружать).
    • РежимРедактирования — установите значение Непосредственно.

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

Проанализируем программный код, который управляет поведением формы:


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

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

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


Способ 2. Использование событий «ПриВыводеСтроки» и «ПриИзмененииФлажка» (Рекомендуемый способ)

Рассмотрим альтернативный, более элегантный и отказоустойчивый метод. Он полностью исключает использование встроенных механизмов изменения строк платформы 1С. Мы будем использовать событие изменения флажка вручную, записывая данные напрямую в объект базы данных.

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

  1. Полностью очистите свойства Данные и ДанныеФлажка у колонки НеВыгружать.
  2. Установите свойство РежимРедактирования в значение Непосредственно.

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


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

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


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

Преимущество метода: Изменение происходит мгновенно по одиночному клику без входа строки в режим редактирования. Это очень удобно для пользователей, которые массово работают со списками товаров.


Способ 3. Перехват события «ПередНачаломИзменения» с отказом от стандартной обработки

Еще один красивый вариант реализации — перехватить попытку редактирования строки, выполнить все действия программно и отменить стандартное поведение платформы, установив параметр Отказ = Истина. Это избавляет форму от лишних перерисовок и гарантирует, что диалоговое окно карточки номенклатуры случайно не откроется.

Для этого способа колонка настраивается аналогично Способу 2 (без привязки к данным), а код обработчика события ПередНачаломИзменения выглядит следующим образом:


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

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


Важные советы по оптимизации производительности

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

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

← На главную