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