Всем привет! Сегодня продолжим погружаться в интерфейс Ревита, на этот раз без дополнительных сложностей в виде новых библиотек — научимся блокировать доступность команд по определённым условиям.
Пример
Допустим, мы написали плагин для запуска в проекте. Запуск в семействе вызовет исключение. Надо предусматривать этот случай, писать код, выводить сообщение "запуск в семействе не предусмотрен" и т.д. При этом у самого Ревита таких проблем нет: мы не можем нарисовать стену в редакторе семейств, ведь кнопки "Стена" просто нет.
Или наш плагин предполагает, что человек выбрал элемент, а потом нажал на кнопку плагина. Было бы удобно сделать так, чтобы человек не мог запустить плагин, не выбрав элемент.
Интерфейс IExternalCommandAvailability
Решение данной задачи достаточно простое: нужно написать класс, реализующий этот интерфейс, и передать его в кнопку, запускающую команду.
Интерфейс содержит всего один метод IsCommandAvailable. Из этого метода мы имеем доступ к выбранным категориям и к UIApplication (а через него — к текущему документу).
Например, так будет выглядеть код, выключающий доступность команды в семействе:
Решим и другую задачу: сделаем так, чтобы команда была доступна лишь тогда, когда среди выбранных элементов есть стены:
Обратите внимание, что в описании к интерфейсу IExternalCommandAvailability сказано:
This callback will be called by Revit's user interface any time there is a contextual change. Therefore, the callback must be fast and is not permitted to modify the active document and be blocking in any way.
Следовательно, мы не можем модифицировать документ в этом методе вообще никак. От себя добавлю, что не стоит добавлять в метод IsCommandAvailable сложную логику, потому что он будет вызываться постоянно. Поэтому в вышеуказанных примерах я стараюсь придерживаться максимально лаконичного стиля, не записывать данные ни в какие переменные, а сразу возвращать результат.
Подключение к команде
Реализовав этот класс, просто подключаем его к команде, передав полное имя класса в свойство AvailibilityClassName. Например, вот так:
button.AvailabilityClassName = $"{nameof(FirstRevitPlugin)}.{nameof(CommandAvailibilityManager)}";
Подключим плагин к Ревиту и посмотрим за результатом:
Заключение
Итоговый код на GitHub (не забываем ставить звёздочки к репозиторию).
Напоминаю про мой телеграм-канал, где я пишу о Revit API. Подписывайтесь, если ещё нет, и до новых встреч!