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