Сообщество программистов Autodesk в СНГ

Статьи => Опубликованные статьи => Тема начата: Александр Ривилис от 10-10-2013, 02:30:06

Название: Создание пользовательской закрепляемой панели
Отправлено: Александр Ривилис от 10-10-2013, 02:30:06
Создание пользовательской закрепляемой панели
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 13:09:30
Добрый день!
Спасибо за статью.
Возник вопрос, а как обращаться к элементам активного документа Revit из закрепляемой панели?
то есть передать в MyControl Document?

Спасибо
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 13:48:53
shss, добрый день.
Точно также, как и из немодальной формы - с помощью обработки события OnIdling. Напрямую никак. Вернее возможно передать в закрепляемую панель активный документ при помощи обработки события ViewActivated, как это описано в статье, но его ни в коем случае нельзя использовать для обращения в элементам документа. Revit почти гарантировано "упадет". Этот способ можно использовать только для заполнения некоторых данных из активного документа при переключении вида.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 14:20:25
Виктор, спасибо за подсказку!
Буду искать в этом направлении.
Ну а в целом, конечно, непонятно назначение данной панели, с одной стороны она как бы "нативная", но обращаться с ней нужно, как с немодальной (некой внешней) формой.
Опять же отслеживать все изменения модели пока "висит" форма, получается невозможно, если не будет кнопочки а ля "Обновить данные" (на примере списка элементов).
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 14:59:43
Нативная то она нативная, тем не менее, как ни крути, она пользовательская и в то же время она не блокирует пользовательский интерфейс, т.е. по сути это и есть немодальная форма, но тесно встроена в интерфейс.
Кнопочку "обновить данные" конечно можно сделать. Другой вопрос на сколько это легко или трудно.
Думаю я напишу статью в ближайшее время как работать с немодальными формами.

По поводу назначения панели. Как пример, в Revit есть встроенный диспетчер проектов с каталогом семейств. Представьте себе собственный каталог онлайн-семейств, когда мы ищем некое семейство в каталоге и загружаем его прямо в проект из интернета, не выполняя никаких лишний действий. При этом каталог можно встроить прямо в интерфейс самого Revit в виде закрепляемой панели. По моему здорово.
Другой пример. Элемент в модели связан с некой сущностью во внешней базе данных. При выделении элемента можно отображать свойства этой сущности из базы данных. Закрепляемая панель как раз подходит для таких случаев.
Т.е. эта возможность безусловна полезна. Но это не значит что ее нужно применять везде подряд.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 15:21:56
Да тут я с Вами, совершенно согласен.
Но все же это странно, что нет доступа даже к БД модели, просто проводя аналогию с Navisworks или AuoCAD из DockablePanel я всегда имею доступ к элементам активной модели.
Статьи про немодальные формы было бы очень интересно почитать.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 15:44:46
shss, про AutoCAD я не подскажу, так как практически не работал с ним. В Navisworks же на сколько мне известно (могу ошибаться), мы можем только читать данные.
Позиция Autodesk по поводу того, почему нельзя откуда попало вызывать методы Revit API своидтся к тому, что в момент когда что-то вы делает с моделью, этот же самый элемент может быть изменен самим Revit'ом или другим приложением и в итоге внутренняя база Revit может поломаться. Возможно все дело в структуре хранения данных и внетренней работы Revit. Как программист, я понимаю, что все это решаемо в теории. На практике может это потребует неимоверхных услиий, вплоть до пееписывания кода с нуля, для того чтобы была возможность вызывать методы Revit API отовсюду. Поэтому придется мириться с тем что есть и находить обходные пути, для того чтобы реализовать ту или иную задачу.
Правда я еще могу понять, почему запрещено изменению модели из другого потока или из любого места кода, но вот почему запрещено даже чтению - я не знаю. Причем если в 2014 версии и ниже еще можно было обращаться к элементам из другого потока именно для чтения данных (хотя и крайне не рекомендовано), то в 2015 Revit падает с ошибкой (http://adn-cis.org/forum/index.php?topic=887.0).
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 15:52:54
Спасибо за развернутый ответ.
Все же, видимо, придется использовать диалоговое окно, хотя, как ни старался, пытался уйти от него.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 15:55:07
А что у вас за задача?
С диалоговыми окнами несомненно проще, но как я сказал, возможно ведь и в закрепляемой панели. Просто придется немного повозиться:)
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 16:00:11
Задача очень простая: используя параметры элементов (высота, длина, объем и т.д.) создавать View Filter и применять его.
То есть для отображения параметров элементов мне надо перебрать их в модели и вывести пользователю, после его выбора создать фильтр и применить его к модели.
Каждый раз открывать диалоговое окно не совсем удобно, причем после применения модель надо повертеть, и если, что-то не нравится изменить фильтр. Прыгать туда-сюда пользователю не удобно.
Поэтому и хотел вынести в закрепляемой панели.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 16:43:40
Вполне логично поместить это в закрепляемую панель.

Вот краткое решение как это грамотно реализовать.

Собственно не так уж и сложно :)

Вот пример кода для модальной формы. Для закрепляемой панели будет похожий код:
Код - C# [Выбрать]
  1.     public partial class Form1 : Form
  2.     {
  3.         private readonly UIControlledApplication _uiControlledApplication;
  4.  
  5.         /// <summary>
  6.         /// В конструктор формы передаем объект типа UIControlledApplication
  7.         /// для дальнейшей подписки на событие OnIdling
  8.         /// </summary>
  9.         /// <param name="uiControlledApplication"></param>
  10.         public Form1(UIControlledApplication uiControlledApplication)
  11.         {
  12.             _uiControlledApplication = uiControlledApplication;            
  13.             InitializeComponent();
  14.         }
  15.  
  16.         private void button1_Click(object sender, EventArgs e)
  17.         {
  18.             // При нажатии на кнопку, подписываемся на событие
  19.            _uiControlledApplication.Idling += _uiControlledApplication_Idling;
  20.            
  21.         }
  22.  
  23.         void _uiControlledApplication_Idling(object sender, Autodesk.Revit.UI.Events.IdlingEventArgs e)
  24.         {
  25.             // Получаем объект типа UIApplication
  26.             var uapp = (UIApplication)(sender);
  27.  
  28.             // и из него получаем активный документ
  29.             var doc = uapp.ActiveUIDocument.Document;
  30.  
  31.             // делаем то что хотим с активным документом
  32.             MessageBox.Show(doc.Title);
  33.  
  34.             // и не забываем отписываться от события.
  35.             _uiControlledApplication.Idling -= _uiControlledApplication_Idling;
  36.         }
  37.     }

И напоследок исходный код демо приложения как обращаться к активному документу из модальной формы. (во волжении)
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 18:47:26
Спасибо за подсказку, Виктор!
я вот тут тоже такое расковырял
http://thebuildingcoder.typepad.com/blog/2009/02/revit-window-handle-and-modeless-dialogues.html (http://thebuildingcoder.typepad.com/blog/2009/02/revit-window-handle-and-modeless-dialogues.html)
но у меня возник вопрос
в варианте с формой, мы передаем форме:
Код - C# [Выбрать]
  1.  App.Form.Show(new Win32Window(ComponentManager.ApplicationWindow));
а в варианте с панелью не получается передать:
Код - C# [Выбрать]
  1. DockablePaneId dpid = new DockablePaneId(new Guid("E6EF9DE9-F5F2-454B-8968-4BA2622E5CE6"));
  2.                 if (dpid != null) {
  3.                     DockablePane dp = commandData.Application.GetDockablePane(dpid);
  4.                 dp.Show();
Поправьте меня если я не прав.

P.S. тут не совсем все так просто, как может показаться на первый взгляд :)
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 19-08-2014, 18:57:37
В случае панели это и не нужно.  В варианте с немодальной формой я передаю идентификатор родительского окна, тем самым указываю форме, что окно Revit является главноым для немодальнйо формы. Это необязательно и необходимо для того, чтобы немодальная форма, например, сворачивалась при сворачивании Revit и при активации окна Revit, форма также появлялась на переднем плане. Можете поэксперементировать с поведенем формы, с передачей параметра new Win32Window(ComponentManager.ApplicationWindow) и без него, чтобы понять разницу.

Соответственно для панели нет необходимости указывать дополнительно, что Revit является родительским окном. Это уже сделано во внутренней реализации панели.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: shss от 19-08-2014, 19:29:47
Все  разобрался, Виктор, огромное спасибо за помощь!
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: SatanaXIII от 12-10-2017, 15:14:10
Здравствуйте. Не могу организовать работу с Revit из закрепляемой панели (WPF).
Пробовал посредством обращения через сохраненный Application, и через внешние события, и через событие простоя.
Получается считывать названия документов и кое чего по мелочи.
Не могу получить доступ к чертежу (PickObjects, например) или изменить что-либо на чертеже.
Из WindowsForms-окна все работает замечательно. Но, применяя неважно какой подход, любое обращение к чертежу из WPF-панели заканчивается выбросом исключения:
Цитировать
{Autodesk.Revit.Exceptions.InvalidOperationException: The active view is non-graphical and does not support capture of the focus for pick operations.
При чем активный вид на самом деле-то правильный и все с ним хорошо.
Как получить доступ к элементам чертежа из WPF-панели?
P.S. Revit 2016.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 13-10-2017, 14:09:17
SatanaXIII, а как вы в итоге вызываете методы из закрепляемой панели?
Стоит отметить, что работа с Revit API возможна только в "правильных" контекстах. Вы не можете вызывать методы Revit API откуда попало. Случай с закрепляемой панелью похож на работу с немодальным окном.

Есть небольшая статья (http://adn-cis.org/zapusk-komandyi-iz-zakreplyaemoj-paneli.html) по этому поводу.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: SatanaXIII от 16-10-2017, 11:36:37
Есть небольшая статья по этому поводу.
Статью читал. В ней сказано, что через событие Idling все же можно добраться до модели ревита.
Стоит отметить, что работа с Revit API возможна только в "правильных" контекстах. Вы не можете вызывать методы Revit API откуда попало. Случай с закрепляемой панелью похож на работу с немодальным окном.
Опять же некоторые методы можно вызывать откуда попало, некоторые нельзя (см. пример). Эта неточность вносит некоторый сумбур.

SatanaXIII, а как вы в итоге вызываете методы из закрепляемой панели?
Приведу пример:
Извините, вам запрещён просмотр содержимого спойлеров.

Таким образом получить список выбранных элементов (GetElementIds) можно, а вот выбрать (PickElementsByRectangle) нет.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: Виктор Чекалин от 16-10-2017, 14:12:25
SatanaXIII,
Когда вызывается метод EventSelect.Raise(); - вот тут то как раз и происходит выполнение метода RevitAPI в неправильном контексте. Последствия могут быть, а могут и не быть.
Вообще изначальная ошибка говорит о том, что вид не подходящий для выбора объектов.
Если вы обработке события Idling отобразить текущий вид, что там будет?
Код - C# [Выбрать]
  1. var currentView = uapp.ActiveUIDocument.ActiveView;
Интересует тип вида и название.
Название: Re: Создание пользовательской закрепляемой панели
Отправлено: SatanaXIII от 16-10-2017, 14:49:31
Когда вызывается метод EventSelect.Raise(); - вот тут то как раз и происходит выполнение метода RevitAPI в неправильном контексте. Последствия могут быть, а могут и не быть.
Почему же в неправильном? Событие же я могу вызвать в любом месте, главное чтобы обработчик был в правильном.

Вообще изначальная ошибка говорит о том, что вид не подходящий для выбора объектов.
Если вы обработке события Idling отобразить текущий вид, что там будет?
Интересует тип вида и название.
Конечно же первым делом я проверил не сбрасывается ли текущий вид на какой-либо другой. Не сбрасывается.
Название: 3D вид: {3D}
Тип вида: ThreeD