При разработке на обычных формах (ОФ) программисты часто сталкиваются с тем, что стандартный динамический список документов (объект ДокументСписок) предназначен в первую очередь для просмотра. Попытка добавить колонку с флажком для быстрой пометки строк часто натыкается на ограничения интерфейса: галка либо не нажимается вовсе, либо требует двойного клика, либо вызывает открытие формы документа. Разберем подробно, как реализовать удобный и быстрый механизм "кликабельной" галки.
Проанализируем ситуацию, когда нам нужно просто пометить несколько документов для дальнейшей обработки (например, для печати или группового изменения), не сохраняя эти пометки в базе данных на постоянной основе. В этом случае мы создадим колонку, которая не связана с данными документа, и будем хранить состояние флажков в памяти формы.
Для начала добавим в табличное поле списка новую колонку, назовем ее КолонкаФлажок. В свойствах колонки установим тип значения Булево, включим свойство ОтображатьФлажок и выключим ОтображатьТекст. Чтобы галка реагировала на клик, нам потребуется написать код в модуле формы.
Рассмотрим пример кода, использующий объект Соответствие для хранения состояния. Использование Соответствие эффективнее, чем Массив, так как поиск ссылки документа происходит мгновенно.
Перем КэшФлажков; // Здесь будем хранить Ссылка -> Булево
Процедура ПриОткрытии()
КэшФлажков = Новый Соответствие;
КонецПроцедуры
Процедура ДокументСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
// Устанавливаем визуальное состояние флажка из кэша
Состояние = КэшФлажков.Получить(ДанныеСтроки.Ссылка);
ОформлениеСтроки.Ячейки.КолонкаФлажок.УстановитьФлажок(?(Состояние = Истина, Истина, Ложь));
КонецПроцедуры
Теперь разберем, как обработать само нажатие. Самый надежный способ в ОФ — перехватить событие Выбор или ЯчейкаПриНажатии. Если мы используем событие Выбор, нам нужно обязательно установить СтандартнаяОбработка = Ложь, чтобы при клике на галку не открывалась форма документа.
Процедура ДокументСписокВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
Если Колонка.Имя = "КолонкаФлажок" Тогда
СтандартнаяОбработка = Ложь; // Отменяем открытие документа
ТекСсылка = ЭлементыФормы.ДокументСписок.ТекущиеДанные.Ссылка;
ТекущееСостояние = КэшФлажков.Получить(ТекСсылка);
// Инвертируем состояние
НовоеСостояние = ?(ТекущееСостояние = Истина, Ложь, Истина);
КэшФлажков.Вставить(ТекСсылка, НовоеСостояние);
// Обновляем только текущую строку для производительности
ЭлементыФормы.ДокументСписок.ОбновитьСтроку(ЭлементыФормы.ДокументСписок.ТекущаяСтрока);
КонецЕсли;
КонецПроцедуры
Если задача стоит иначе и флажок является реальным реквизитом документа (типа Булево), мы можем столкнуться с тем, что для изменения значения пользователю нужно сначала "войти" в ячейку (первый клик), а затем нажать на галку (второй клик). Это неудобно. Выясним, как сделать это за одно нажатие.
Выполним следующие шаги в конфигураторе:
ТолькоПросмотр.Важный нюанс: если мы разрешаем редактирование в списке документов, система будет пытаться записать объект при каждом изменении флажка. Проанализируем последствия: это может привести к постоянному изменению версии объекта, даты изменения и автора. Чтобы избежать лишних проверок при записи, в модуле документа можно использовать флаг ОбменДанными.Загрузка = Истина, если это допустимо вашей бизнес-логикой.
Рассмотрим более продвинутый и "чистый" с точки зрения архитектуры способ. Если пометки должны сохраняться между сеансами работы пользователя, но мы не хотим менять структуру самих документов, создадим независимый РегистрСведений (например, ПользовательскиеМетки) с измерениями Пользователь, Документ и ресурсом Отметка (Булево).
Посмотрим, как оптимизировать вывод данных, чтобы список не "тормозил" при прокрутке. Вместо события ПриВыводеСтроки, которое вызывается для каждой отрисовываемой строки, используем ПриПолученииДанных. Это событие позволяет получить данные сразу для всей пачки строк, видимых на экране, одним запросом.
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
// Собираем все ссылки на документы, которые сейчас видны на экране
МассивСсылок = Новый Массив;
СоответствиеСтрок = Новый Соответствие;
Для Каждого ОформлениеИз Списка ОформленияСтрок Цикл
МассивСсылок.Добавить(ОформлениеИз.ДанныеСтроки.Ссылка);
СоответствиеСтрок.Вставить(ОформлениеИз.ДанныеСтроки.Ссылка, ОформлениеИз);
КонецЦикла;
// Получаем данные из регистра одним запросом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПользовательскиеМетки.Документ КАК Ссылка,
| ПользовательскиеМетки.Отметка КАК Отметка
|ИЗ
| РегистрСведений.ПользовательскиеМетки КАК ПользовательскиеМетки
|ГДЕ
| ПользовательскиеМетки.Документ В(&МассивСсылок)
| И ПользовательскиеМетки.Пользователь = &ТекущийПользователь";
Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
Запрос.УстановитьПараметр("ТекущийПользователь", ПараметрыСеанса.ТекущийПользователь);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Оформление = СоответствиеСтрок.Получить(Выборка.Ссылка);
Если Оформление <> Неопределено Тогда
Оформление.Ячейки.КолонкаФлажок.УстановитьФлажок(Выборка.Отметка);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если вам не принципиально, в каком месте строки будет находиться галка, разберем самый простой встроенный механизм табличного поля. У любого табличного поля в ОФ есть свойство Флажки.
Если его включить, в левой части списка появится системная колонка с чекбоксами. Проанализируем работу с ними:
ЭлементыФормы.ТабличноеПоле.ОтмеченныеСтроки.ЭлементыФормы.ДокументСписок.ОтмеченныеСтроки.Добавить(СтрокаДокумента).Этот метод идеально подходит для задач типа "Выбрать документы для групповой печати", так как он стандартен для платформы и привычен многим пользователям.
Выясним, какой метод выбрать в вашем случае:
ПриПолученииДанных.Не забывайте про свойство СтандартнаяОбработка = Ложь в обработчиках нажатия, иначе вместо переключения флажка вы будете постоянно открывать формы документов, что вызовет раздражение у пользователей.