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