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