1С Платформа 8.3. Изучаем немодальные окна

Кто программировал в версиях 1С 8.1 и 8.2 помнят различные процедуры, вызывающие модальные окна: Предупреждение, Вопрос и т.п. С появлением платформы 8.3. все немного изменилось, и в полнее возможно, что код, написанный для конфигураций на платформе 1С 8.2, не будет работать на платформе 1С 8.3. При использовании вышеперечисленных процедур вызова модальных окон могут появляться ошибки подобного рода: «Использование модальных окон в данном режиме запрещено!».

Всему виной свойство конфигурации «Режим использования модальности»

У этого свойства может быть три значения:
• Использовать – тогда процедуры типа Предупреждение, Вопрос и тп будут работать;
• Использовать с предупреждениями – процедуры типа Предупреждение, Вопрос и тп будут работать, но будет выходить сообщение;
• Не использовать — процедуры типа Предупреждение, Вопрос и тп работать не будут.

Поэтому если возникла такая ошибка, то есть два варианта решения проблемы. Первый вариант – топорный, изменить свойство конфигурации «Режим использования модальности». Этот вариант в некоторых случаях может иметь место. Но имейте в виду, что он не применим, если конфигурация планируется запускаться под web-клиентом.

Второй вариант – переписать все имеющиеся процедуры вызова модальных окон на процедуры, использующие немодальные окна. Процедур, которые потребуется заменить в случае перехода с платформы 8.2 на 8.3, довольно таки много, я приведу только некоторые из них:

• Предупреждение – ПоказатьПредупреждение
• Вопрос – ПоказатьВопрос
• ВвестиЧисло – ПоказатьВводЧисла
• ВвестиСтроку- ПоказатьВводСтроки
• ВвестиДату – ПоказатьВводДаты
• ВвестиЗначение — ПоказатьВвводЗначения

Основное отличие всех вышеперечисленных новых процедуры, то, что ввод-вывод информации осуществляется асинхронно. Что это значит? Пока Вы решаете нажать или не нажать кнопку «ОК», как ответить на вопрос, или какое число ввести, идет выполнение кода программы. Для этого в метод необходимо передать название процедуры, которая будет обработчиком ожидания. И сработает, когда вы нажмете кнопку «ОК».

В тоже время не стоит путать асинхронность с параллельностью. Код, который у Вас сработает в процедуре обработчике ожидания, не будет выполняться параллельно основному коду. Он сработает после выполнения этого кода.
Рассмотрим эту особенность более подробно. Для этого я создал простую обработку, в которой будет выполняться следующий код:

&НаКлиенте
Процедура КомандаПредупреждение(Команда)

        Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияПредупреждения",ЭтаФорма,Параметры);

        ПоказатьПредупреждение(Оповещение,НСтр("ru = ‘Предупрежение'"),,"!!!");

        Для н = 1 по 10 Цикл
             Сообщить("Работает цикл" + н);
        КонецЦикла;
КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияПредупреждения(ДопПараметры) Экспорт

          Сообщить("После закрытия предупреждения");

КонецПроцедуры

Поясню написанный выше код: мы создали обработчик ожидания с помощью объекта «ОписаниеОповещения», где в качестве первого параметра указали название процедуры, которая должна сработать после нажатия кнопки «ОК» окна предупреждения. В следующей строке мы применили процедуру «ПоказатьПредупреждение», где в качестве первого параметра указали написанный выше обработчик ожидания. Именно после нажатия кнопки «ОК» сработает процедура «ПослеЗакрытияПредупреждения». А в конце мы написали простой цикл.

Обратите внимание на рисунок, цикл сработал до того, как мы нажали на кнопку «ОК» окна предупреждении. Это и есть, по сути, асинхронное выполнение кода.
Теперь попробуем применить вызов предупреждения внутри цикла

&НаКлиенте
Процедура КомандаПредупреждение(Команда)
 
          Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияПредупреждения",ЭтаФорма,Параметры);

          Для н = 1 по 10 Цикл

               Если н = 5 Тогда
                     ПоказатьПредупреждение(Оповещение,НСтр("ru = 'Предупрежение'"),,"!!!");
               КонецЕсли;

               Сообщить("Работает цикл " + н);

          КонецЦикла;

КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияПредупреждения(ДопПараметры) Экспорт

           Сообщить("После закрытия предупреждения");

КонецПроцедуры

И всё равно, выполнение цикла произойдет до того как будет нажата кнопка «ОК». Точно так же будет работать метод, если мы уберем оповещение.

&НаКлиенте
Процедура КомандаПредупреждение(Команда)

    Для н = 1 по 10 Цикл

        Если н = 2 Тогда
            ПоказатьПредупреждение(,НСтр("ru = 'Предупрежение'"),,"!!!");
        КонецЕсли;

        Сообщить("Работает цикл " + н);

    КонецЦикла;

КонецПроцедуры

В связи с переходом на немодальные окна потребуется пересмотреть принципы работы диалогов пользователя, где нужно ответить, как вариант, да-нет.
Если в модальных окнах можно было использовать такой код:

&НаКлиенте
Процедура КомандаПредупреждение(Команда)

      Ответ = Вопрос(НСтр("ru = 'Какой будет ответ на вопрос?'"),РежимДиалогаВопрос.ДаНет);

      Если Ответ = КодВозвратаДиалога.Да Тогда
            Сообщить("Да");
      иначе
            Сообщить("Нет");
      КонецЕсли;

КонецПроцедуры

То при использовании немодальных окон, код будет следующим:

&НаКлиенте
Процедура КомандаПредупреждение(Команда)

         Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияЗакрытияВопроса",ЭтаФорма,Параметры);

         ПоказатьВопрос(Оповещение, НСтр("ru = ‘Какой будет ответ на вопрос?'"),РежимДиалогаВопрос.ДаНет);

КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияЗакрытияВопроса(Результат, ДопПараметры) Экспорт

          Если Результат = КодВозвратаДиалога.Да тогда
                Сообщить("Ответили ""Да""");
          иначе
                Сообщить("Ответили ""Нет""");
          КонецЕсли;

КонецПроцедуры

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

Рассмотрим еще один вариант, если нам нужно что-то сделать в обработчике события в зависимости от той или иной ситуации в цикле. Допустим, мы записываем документы, и нужно задать какой-то вопрос, от которого будет зависеть запись документа (допустим сменить склад). Понятно что таких документов может быть много и их нужно как-то накопить. Для этого можно использовать параметр, который мы передаем в обработчик ожидания (третий параметр конструктора объекта ОписаниеОповещения).

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

И при вызове обработчика события, буду рекурсивно прибавлять этот реквизит. Тем самым мы будем знать, для какого по индексу события вызван наш обработчик.

&НаКлиенте
Процедура КомандаПредупреждение(Команда)

        СчетчикВызова = 0;

        Массив = Новый Массив;
        Структура = Новый Структура("Массив",Массив);
        Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияЗакрытияВопроса",ЭтаФорма,Структура);

        Для н = 1 по 100 Цикл

              Если н = 10  Тогда
                  Структура.Массив.Добавить(н);
                  ПоказатьВопрос(Оповещение, НСтр("ru = ‘Какой будет ответ на вопрос?'"),РежимДиалогаВопрос.ДаНет);
              КонецЕсли;

              Если н = 50 Тогда
                  Структура.Массив.Добавить(н);
                  ПоказатьВопрос(Оповещение, НСтр("ru = ‘Какой будет ответ на вопрос?'"),РежимДиалогаВопрос.ДаНет);
              КонецЕсли;

              Сообщить("Работает цикл, н = " + н);

         КонецЦикла;

КонецПроцедуры

&НаКлиенте
Процедура ПослеЗакрытияЗакрытияВопроса(Результат, ДопПараметры) Экспорт

       Если Результат = КодВозвратаДиалога.Да тогда
             Сообщить("Ответили ""Да"", н = " + ДопПараметры.Массив[СчетчикВызова]);
       иначе
             Сообщить("Ответили ""Нет"", н = " + ДопПараметры.Массив[СчетчикВызова]);
       КонецЕсли;

       СчетчикВызова = СчетчикВызова + 1;
КонецПроцедуры

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

Как мы видим, использование асинхронности модальных окон может существенно улучшить некоторые моменты разработки. Но в тоже время переход с модальных окон типа Предупреждение, Вопрос на немодальные окна: ПоказатьПредупреждение, ПоказатьВопрос накладывает определенные проблемы: алгоритмы, которые были раньше вполне возможно потребуют существенной переработки. Необходим будет какой-то рефакторинг кода. Причем иной раз очень серьезный.

Книга «Программировать в 1С за 11 шагов»

Изучайте программирование в 1С в месте с моей книги «Программировать в 1С за 11 шагов»

  1. Книга написана понятным и простым языком — для новичка.
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Научитесь понимать архитектуру 1С;
  4. Станете писать код на языке 1С;
  5. Освоите основные приемы программирования;
  6. Закрепите полученные знания при помощи задачника;

Книга «Основы разработки в 1С: Такси»

Отличное пособие по разработке в управляемом приложении 1С, как для начинающих разработчиков, так и для опытных программистов.

  1. Очень доступный и понятный язык изложения
  2. Книга посылается на электронную почту в формате PDF. Можно открыть на любом устройстве!
  3. Поймете идеологию управляемого приложения 1С
  4. Узнаете, как разрабатывать управляемое приложение;
  5. Научитесь разрабатывать управляемые формы 1С;
  6. Сможете работать с основными и нужными элементами управляемых форм
  7. Программирование под управляемым приложением станет понятным

Промо-код на скидку в 15% — 48PVXHeYu


Если Вам помог этот урок решить какую-нибудь проблему, понравился или оказался полезен, то Вы можете поддержать мой проект, перечислив любую сумму:

можно оплатить вручную:

Яндекс.Деньги — 410012882996301
Web Money — R955262494655

Вступайте в мои группы:

Вконтакте: https://vk.com/1c_prosto
Фейсбуке: https://www.facebook.com/groups/922972144448119/
ОК: http://ok.ru/group/52970839015518
Твиттер: https://twitter.com/signum2009

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *