Гибкое управление свойствами доступности элементов управления в обычных формах 1С: Предприятия 8.х

от автора

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

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

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

ПолучитьСписокУправлениеВидимостью(); ПолучитьСписокУправлениеДоступностью(); ПолучитьСписокУправлениеТолькоПросмотр(); ПолучитьСписокДоступаКУправлениюВидимостью(); 

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

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

Исходный код общего модуля УправлениеДоступом

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

Например, у нас есть табличное поле Товары, в котором присутствует колонка СкидкаПоДисконтнойКарте. Колонка видна только тогда, когда дисконтная карта проставлена в документ, т.е. реквизит ДисконтнаяКарта является заполненным. Соответственно, условие списока управления видимостью для колонки СкидкаПоДисконтнойКарте будет следующим:

Вторая часть когда — это функции, которые отвечают за формирование списков доступности. Они располагаются непосредственно в форме и являются экспортируемыми. Я немного отошел от стандарта 1С и заменил метод ПолучитьСписокДоступаКУправлениюВидимостью() на ПолучитьСписокУправлениеРедактированиемТекста(). Просто мне кажется, что так удобнее и логичнее. Ниже приведен шаблон кода с этими функциями:

Исходный код функций формирования списков управления доступом

//////////////////////////////////////////////////////////////////////////////// // ЭКСПОРТНЫЕ ПРОЦЕДУРЫ И ФУНКЦИИ  Функция ПолучитьСписокУправлениеВидимостью() Экспорт        СписокУправлениеВидимостью = Новый СписокЗначений;        Возврат СписокУправлениеВидимостью;    КонецФункции  Функция ПолучитьСписокУправлениеДоступностью() Экспорт        СписокУправлениеДоступностью = Новый СписокЗначений;        Возврат СписокУправлениеДоступностью;    КонецФункции  Функция ПолучитьСписокУправлениеРедактированиемТекста() Экспорт        СписокУправлениеРедактированиемТекста = Новый СписокЗначений;        Возврат СписокУправлениеРедактированиемТекста;    КонецФункции    Функция ПолучитьСписокУправлениеТолькоПросмотр() Экспорт        СписокУправлениеТолькоПросмотр = Новый СписокЗначений;        Возврат СписокУправлениеТолькоПросмотр;    КонецФункции 

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

//////////////////////////////////////////////////////////////////////////////// // ПРОЦЕДУРЫ И ФУНКЦИИ ОБЩЕГО НАЗНАЧЕНИЯ  Процедура УстановитьДоступ()      УправлениеДоступом.УстановитьДоступ(ЭтаФорма);  КонецПроцедуры 

Чтобы было все нагляднее и понятнее, давайте рассмотрим следующий пример. Допустим, что у нас есть форма. На ней расположен флажок НаличнаяПродажа (булево), флажок ПробиватьФискальныйЧек (булево), поле ввода ДисконтнаяКарта (ссылка на справочник ДисконтныеКарты), поле ввода Комментарий (строка) и табличное поле Товары. Все связаны с одноименными реквизитами. У табличного поля есть колонка с именем СкидкаПоДисконтнойКарте (число). Кроме этого, есть командная панель ОсновныеДействияФормы, на которой размещена кнопка ПробитьЧек. Определим некоторые условия:

  1. Если установлен флажок НаличнаяПродажа, флажок ПробиватьФискальныйЧек видим и поле ДисконтнаяКарта доступно для ввода.
  2. Если стоит флажок ПробиватьФискальныйЧек, кнопка ПробитьЧек доступна.
  3. Если поле ДисконтнаяКарта заполнено, то видна колонка СкидкаПоДисконтнойКарте табличной части Товары и поле ввода Комментарий доступно для редактирования.

Тогда для нашего примера функции определения списков примут следующий вид:

Исходный код функций для примера

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

Теперь достаточно вызвать процедуру формы УстановитьДоступ(), и мы получим то состояние элементов, которые задали.

Хочется выделить следующий момент. В списки можно можно добавлять пути к элементам формы. Например, для вышеприведенного примера с таблицей Товары имя элемента определяем как «Товары.Колонки.СкидкаПоДисконтнойКарте». Или путь к кнопке ПробитьЧек. Можно использовать множественные вложения, вроде «ИмяКоманднойПанели.Кнопки.ИмяПодменю.Кнопки.ИмяКнопки».

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

Спасибо за внимание.

ссылка на оригинал статьи http://habrahabr.ru/post/214581/


Комментарии

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

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