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