Выбор подходящего вида при вставке семейства
Мэт Тэйлор (Matt Taylor) из компании WSP поднял одну важную проблему, связанную с использованием метода PromptForFamilyInstancePlacement в Revit 2014.
Также он пошел верным путем, предложив и реализовав решение этой проблемы.
Вопрос: Одним из важных нововведений в Revit API 2014 является возможность вызова внешней команды при активном Диспетчере проекта. Если Диспетчер проектов активен, и вызывается команда, которая использует метод PromptForFamilyInstancePlacement, то возникнет ошибка, так как будет произведена попытка вставки семейства на активный вид. Активным видом в этом случае является Диспетчер проекта и, очевидно, что в него семейство вставить нельзя.
В справке по API для метода PromptForFamilyInstancePlacement отмечается, что пользователь не может сменить вид во время операции вставки семейства.
Если у вас только один открытый вид, в который вы можете вставить семейство, то довольно легко сделать его активным перед вызовом метода PromptForFamilyInstancePlacement. Но что делать если их много? Как мне получить последний активный вид, который был до активации Диспетчера проекта?
Может быть что-то реализовать в обработке события ViewActivated? Или предложить пользователю выбрать вид, прежде чем вызывать метод PromptForFamilyInstancePlacement? Но для Revit 2013 и ниже это действие выглядит не логичным.
Ответ: Я думаю вариант с обработкой события ViewActivated вполне жизнеспособен и не очень сложен в реализации. Нужно всего лишь в обработке этого события сохранять какие виды были активными. Перед вызовом PromptForFamilyInstancePlacement активировать последний вид, в котором можно выполнить операцию вставки семейства. Думаю, это решит вашу проблему.
Отклик на ответ: Вот архив проекта с решением проблемы. Большинство кода взято из вашего блога, хоть и на VB.NET.
Реализация оказалась гораздо сложней, чем я думал.
В методе OnStartup инициализируем словарь, содержащий последний валидный, для метода PromptForFamilyInstancePlacement, вид для каждого документа. И подпишемся на событие ViewActivated.
- ''' <summary>
- ''' Map document title to last valid view element id
- ''' </summary>
- Public Shared viewHash As Hashtable
- Public Function OnStartup( _
- ByVal application As UIControlledApplication) _
- As Result Implements IExternalApplication.OnStartup
- Try
- viewHash = New Hashtable
- AddHandler application.ViewActivated,
- AddressOf OnViewActivated
- Return Result.Succeeded
- Catch ex As Exception
- Return Result.Failed
- End Try
- End Function
- Private Shared Function ViewDescription( _
- ByVal v As View) As String
- "view '{0}' in document '{1}'",
- v.Name, v.Document.Title)
- End Function
- Private Sub OnViewActivated( _
- ByVal sender As Object,
- ByVal e As ViewActivatedEventArgs)
- Dim docTitle As String = e.Document.Title
- Dim vPrevious As View = e.PreviousActiveView
- Dim vCurrent As View = e.CurrentActiveView
- If Not (vCurrent.ViewType = ViewType.SystemBrowser _
- OrElse vCurrent.ViewType = ViewType.ProjectBrowser) Then
- If viewHash.ContainsKey(docTitle) Then
- viewHash.Item(docTitle) = vCurrent.Id
- Else
- viewHash.Add(docTitle, vCurrent.Id)
- End If
- End If
- Dim s As String = If(
- (vPrevious Is Nothing),
- "no view at all",
- "previous " + ViewDescription(vPrevious))
- Debug.Print(
- "Switching from {0} to new {1}.",
- s, ViewDescription(vCurrent)))
- End Sub
Зная эту информацию, мы всегда можем переключиться на нужный вид, перед вызовом PromptForFamilyInstancePlacement .
- ' According to the help for
- ' PromptForFamilyInstancePlacement:
- ' "Users are not permitted to change the active
- ' view during this placement operation (the
- ' operation will be completed)."
- ' Here's the fix, which only needs to work for 2014.
- ' (With previous versions, the ribbon items are
- ' greyed out if the project browser is active.)
- Dim actView As DB.View = doc.ActiveView
- If actView.ViewType = DB.ViewType.SystemBrowser _
- OrElse actView.ViewType = DB.ViewType.ProjectBrowser Then
- ' Get stored view id.
- If AppCommand.viewHash.ContainsKey(doc.Title) Then
- Dim prevValidViewId As DB.ElementId _
- = AppCommand.viewHash.Item(doc.Title)
- Dim elem As DB.Element = doc.GetElement(
- prevValidViewId)
- If elem IsNot Nothing Then
- Dim view As DB.View = TryCast(elem, DB.View)
- If view IsNot Nothing Then
- ' TODO: Check that view is valid for the
- ' placement of this type of family symbol,
- ' otherwise get another view.
- ' (Likely to be the case, as the user
- ' will normally click a ribbon item as
- ' part of the context of what they're doing.)
- docUI.ActiveView = view
- End If
- End If
- End If
- End If
- docUI.PromptForFamilyInstancePlacement(
- FamilySymbol)
Спасибо Мэту за то что указал на существование проблемы и за элегантное ее решение!
Обсуждение: http://adn-cis.org/forum/index.php?topic=199
Опубликовано 05.09.2013