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

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

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

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

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

Это одна из самых частых причин «тихой» блокировки кнопок платформой 1С. У любого элемента управления типа «Кнопка» на обычной форме есть свойство ИзменяетДанные. Если этот флаг установлен (по умолчанию для кнопки ОК он часто активен), платформа автоматически управляет доступностью кнопки в зависимости от состояния модифицированности формы и прав пользователя.

Если форма открывается в режиме просмотра, или платформа по какой-то причине считает, что данные формы не были изменены, кнопка с установленным флагом ИзменяетДанные блокируется автоматически.

Решение проблемы:

  1. Откроем форму выбора в конфигураторе.
  2. Перейдем в свойства проблемной кнопки (ОК или созданной кнопки дубликата).
  3. Найдем свойство ИзменяетДанные и снимем с него флажок (установим в значение Ложь).
  4. Если кнопка перестанет отвечать за автоматическое закрытие, пропишем обработку ее нажатия вручную.

Причина 2. Неявная установка свойства «ТолькоПросмотр»

Даже если в модулях формы нет явного кода ЭтаФорма.ТолькоПросмотр = Истина;, платформа 1С может перевести форму в режим просмотра самостоятельно. Это происходит в следующих случаях:

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

В обработчик события ПриОткрытии модальной формы добавим запись в технологический журнал или Журнал регистрации 1С:


Процедура ПриОткрытии()
    // Проверяем доступность кнопки программно
    Если Не ЭлементыФормы.КнопкаОК.Доступность Тогда
        ЗаписьЖурналаРегистрации("ОтладкаФормыВыбора",
            УровеньЖурналаРегистрации.Предупреждение,
            ,
            ,
            "Кнопка ОК недоступна! ТолькоПросмотр формы: " + Строка(ЭтотОбъект.ТолькоПросмотр) + 
            ", Модифицированность: " + Строка(ЭтотОбъект.Модифицированность) +
            ", Пользователь: " + ИмяПользователя());
    КонецЕсли;
КонецПроцедуры

Проанализировав Журнал регистрации после очередного обращения пользователя, мы точно узнаем, была ли форма открыта в режиме «Только просмотр».

Причина 3. Потеря связи с владельцем формы и фокуса ввода

Обычные формы крайне чувствительны к иерархии вызовов и фокусу окон. Если цепочка открытия выглядит так: Документ -> Немодальная форма подбора -> Модальная форма выбора, то при переключении пользователя на другие приложения Windows фокус окон может сбиться.

Платформа теряет связь с ВладелецФормы (элементом-получателем значения), из-за чего считает, что выбор совершать некуда, и делает кнопку ОК недоступной. Чтобы этого избежать, всегда явно передавайте владельца при открытии формы:


// Вместо неявного вызова:
// ОткрытьФормуМодально("Справочник.Номенклатура.ФормаВыбора");

// Используем явную передачу владельца (ЭлементНазначения):
ПараметрыФормы = Новый Структура;
ОткрытьФормуМодально("Справочник.Номенклатура.ФормаВыбора", ПараметрыФормы, ЭлементНазначения);

Также рекомендуется принудительно устанавливать фокус ввода при открытии формы, используя метод Активизировать() для основного табличного поля.

Причина 4. Сброс «Режима выбора» у табличного поля списка

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

Иногда при программной установке отборов или обновлении динамического списка свойство РежимВыбора табличного поля сбрасывается. Проанализируем решение этой проблемы: принудительно установим свойство при инициализации окна.


Процедура ПриОткрытии()
    // Гарантируем, что табличное поле работает в режиме выбора
    ЭлементыФормы.СправочникСписок.РежимВыбора = Истина;
КонецПроцедуры

Причина 5. Альтернативный обход через «ОповеститьОВыборе»

Если стандартное поведение платформы по закрытию формы кнопкой ОК продолжает сбоить из-за особенностей релиза платформы 8.3 в режиме совместимости с 8.2, мы можем полностью отказаться от стандартного системного действия выбора.

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

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

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

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

← На главную