Revit document provides a few events for programs to monitor document related operations such as saving, saved, saving as, saved as, closing, closed, printing, and printed.
Let’s create handlers for all these document events first:
Imports System
Imports System.Text
Imports System.Xml
Imports System.Linq
Imports System.Reflection
Imports System.ComponentModel
Imports System.Collections
Imports System.Collections.Generic
Imports System.Windows
Imports System.Windows.Media.Imaging
Imports System.Windows.Forms
Imports System.IO
Imports Autodesk.Revit.ApplicationServices
Imports Autodesk.Revit.Attributes
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.DB.Events
Imports Autodesk.Revit.DB.Architecture
Imports Autodesk.Revit.DB.Structure
Imports Autodesk.Revit.DB.Mechanical
Imports Autodesk.Revit.DB.Electrical
Imports Autodesk.Revit.DB.Plumbing
Imports Autodesk.Revit.DB.Analysis
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.UI.Selection
Imports Autodesk.Revit.UI.Events
Imports Autodesk.Revit.Collections
Imports Autodesk.Revit.Exceptions
Imports Autodesk.Revit.Utility
Imports RvtApplication = Autodesk.Revit.ApplicationServices.Application
Imports RvtDocument = Autodesk.Revit.DB.Document
Public Class DocEventHandlers1
Public Shared Sub DocEvent_DocumentClosing_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("Document DocumentClosing")
End Sub
Public Shared Sub DocEvent_DocumentPrinted_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentPrinted")
End Sub
Public Shared Sub DocEvent_DocumentPrinting_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentPrinting")
End Sub
Public Shared Sub DocEvent_DocumentSaved_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentSaved")
End Sub
Public Shared Sub DocEvent_DocumentSavedAs_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentSavedAs")
End Sub
Public Shared Sub DocEvent_DocumentSaving_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentSaving")
End Sub
Public Shared Sub DocEvent_DocumentSavingAs_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("DocumentSavingAs")
End Sub
Public Shared Sub DocEvent_ViewPrinted_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("ViewPrinted")
End Sub
Public Shared Sub DocEvent_ViewPrinting_Handler(ByVal sender As Object, ByVal args As EventArgs)
MessageBox.Show("ViewPrinting")
End Sub
End Class
Next, we prepare two static methods which can help subscribe and unsubscribe all the events to and from a Document object:
Public Class DocEventSubscriber
'…
'…
Public Shared Sub SubscribeToDoc(ByVal doc As RvtDocument)
AddHandler doc.DocumentClosing, AddressOf DocEventHandlers1.DocEvent_DocumentClosing_Handler
AddHandler doc.DocumentPrinted, AddressOf DocEventHandlers1.DocEvent_DocumentPrinted_Handler
AddHandler doc.DocumentPrinting, AddressOf DocEventHandlers1.DocEvent_DocumentPrinting_Handler
AddHandler doc.DocumentSaved, AddressOf DocEventHandlers1.DocEvent_DocumentSaved_Handler
AddHandler doc.DocumentSavedAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavedAs_Handler
AddHandler doc.DocumentSaving, AddressOf DocEventHandlers1.DocEvent_DocumentSaving_Handler
AddHandler doc.DocumentSavingAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavingAs_Handler
AddHandler doc.ViewPrinted, AddressOf DocEventHandlers1.DocEvent_ViewPrinted_Handler
AddHandler doc.ViewPrinting, AddressOf DocEventHandlers1.DocEvent_ViewPrinting_Handler
End Sub
Public Shared Sub UnsubscribeFromDoc(ByVal doc As RvtDocument)
RemoveHandler doc.DocumentClosing, AddressOf DocEventHandlers1.DocEvent_DocumentClosing_Handler
RemoveHandler doc.DocumentPrinted, AddressOf DocEventHandlers1.DocEvent_DocumentPrinted_Handler
RemoveHandler doc.DocumentPrinting, AddressOf DocEventHandlers1.DocEvent_DocumentPrinting_Handler
RemoveHandler doc.DocumentSaved, AddressOf DocEventHandlers1.DocEvent_DocumentSaved_Handler
RemoveHandler doc.DocumentSavedAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavedAs_Handler
RemoveHandler doc.DocumentSaving, AddressOf DocEventHandlers1.DocEvent_DocumentSaving_Handler
RemoveHandler doc.DocumentSavingAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavingAs_Handler
RemoveHandler doc.ViewPrinted, AddressOf DocEventHandlers1.DocEvent_ViewPrinted_Handler
RemoveHandler doc.ViewPrinting, AddressOf DocEventHandlers1.DocEvent_ViewPrinting_Handler
End Sub
'…
'…
End Class
Last, we can call the methods to subscribe these events to the active document in an external command and unsubscribe them when necessary.
DocEventSubscriber.SubscribeForDoc(CachedDoc);
As can be seen above, it is straightforward to create document event handlers and subscribe them to the active document that a command is going to operate on. However, it will be very tricky to subscribe document events to all documents including existing ones and those that will be opened or created later in the whole Revit session.
Now let’s look at how to subscribe document events to all documents both existing and coming.
To achieve this seemingly simple goal, a few other factors have to be involved such as document collection (Application.Documents), Application events, and UIApplication events. And the subscription needs to happen in an external application rather than an external command.
It is obvious to take into account the document collection of the Revit Application as we need to loop through them to subscribe events or unsubscribe them when necessary, but it is not obvious for the other two, Application events, and UIApplication events. A simple question may just arise, what particular events of the two classes to use and how?
In terms of the UIApplication events, the ViewActivated is a must and the ApplicationClosing is optional; in terms of the Application events, the DocumentCreated and DocumentOpened are necessary and the DocumentClosing is good to use.
The ViewActivated is the only entry point in the UIApplication for us to hook the document event handlers into the Application and the Document world as only at this moment a document is about to be created and the event argument provides access to the Document and in turn the Revit Application. So we forward the event subscription from the UIControlledApplication to the Application object in the callback of the ViewActivated event. The ApplicationClosing can be used to unsubscribe document events when the Revit Application is going to quit, and we do not really have to worry about it since the whole application will be disposed anyway.
The DocumentCreated and DocumentOpened events need to be used to monitor when a new document has been created or opened so as for our programs to subscribe events to it. When the DocumentClosing event is broadcasting, we can unsubscribe events to the document but it’s not absolutely necessary as the whole document and any of its events will be destroyed anyway.
Here is the whole document event subscriber class:
Imports System.Text
Imports System.Xml
Imports System.Linq
Imports System.Reflection
Imports System.ComponentModel
Imports System.Collections
Imports System.Collections.Generic
Imports System.Windows
Imports System.Windows.Media.Imaging
Imports System.Windows.Forms
Imports System.IO
Imports Autodesk.Revit.ApplicationServices
Imports Autodesk.Revit.Attributes
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.DB.Events
Imports Autodesk.Revit.DB.Architecture
Imports Autodesk.Revit.DB.Structure
Imports Autodesk.Revit.DB.Mechanical
Imports Autodesk.Revit.DB.Electrical
Imports Autodesk.Revit.DB.Plumbing
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.UI.Selection
Imports Autodesk.Revit.UI.Events
Imports Autodesk.Revit.Collections
Imports Autodesk.Revit.Exceptions
Imports Autodesk.Revit.Utility
Imports RvtApplication = Autodesk.Revit.ApplicationServices.Application
Imports RvtDocument = Autodesk.Revit.DB.Document
Public Class DocEventSubscriber
Private _uiCtrApp As UIControlledApplication
Private Shared _app As RvtApplication
Private Shared _registered As Boolean
Public Sub New(ByVal app As UIControlledApplication)
_uiCtrApp = app
_registered = False
AddHandler _uiCtrApp.ViewActivated, AddressOf UIAppEvent_ViewActivated_Handler
AddHandler _uiCtrApp.ApplicationClosing, AddressOf UIAppEvent_ApplicationClosing_Handler
End Sub
Public Shared Sub SubscribeForApplication(ByVal app As RvtApplication)
AddHandler app.DocumentOpened, AddressOf AppEvent_DocumentOpened_Handler
AddHandler app.DocumentCreated, AddressOf AppEvent_DocumentCreated_Handler
AddHandler app.DocumentClosing, AddressOf AppEvent_DocumentClosing_Handler
End Sub
Public Shared Sub UnsubscribeForApplication(ByVal app As RvtApplication)
For Each doc As RvtDocument In app.Documents
UnsubscribeFromDoc(doc)
Next
RemoveHandler app.DocumentOpened, AddressOf AppEvent_DocumentOpened_Handler
RemoveHandler app.DocumentCreated, AddressOf AppEvent_DocumentCreated_Handler
RemoveHandler app.DocumentClosing, AddressOf AppEvent_DocumentClosing_Handler
End Sub
Public Shared Sub SubscribeToDoc(ByVal doc As RvtDocument)
AddHandler doc.DocumentClosing, AddressOf DocEventHandlers1.DocEvent_DocumentClosing_Handler
AddHandler doc.DocumentPrinted, AddressOf DocEventHandlers1.DocEvent_DocumentPrinted_Handler
AddHandler doc.DocumentPrinting, AddressOf DocEventHandlers1.DocEvent_DocumentPrinting_Handler
AddHandler doc.DocumentSaved, AddressOf DocEventHandlers1.DocEvent_DocumentSaved_Handler
AddHandler doc.DocumentSavedAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavedAs_Handler
AddHandler doc.DocumentSaving, AddressOf DocEventHandlers1.DocEvent_DocumentSaving_Handler
AddHandler doc.DocumentSavingAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavingAs_Handler
AddHandler doc.ViewPrinted, AddressOf DocEventHandlers1.DocEvent_ViewPrinted_Handler
AddHandler doc.ViewPrinting, AddressOf DocEventHandlers1.DocEvent_ViewPrinting_Handler
End Sub
Public Shared Sub UnsubscribeFromDoc(ByVal doc As RvtDocument)
RemoveHandler doc.DocumentClosing, AddressOf DocEventHandlers1.DocEvent_DocumentClosing_Handler
RemoveHandler doc.DocumentPrinted, AddressOf DocEventHandlers1.DocEvent_DocumentPrinted_Handler
RemoveHandler doc.DocumentPrinting, AddressOf DocEventHandlers1.DocEvent_DocumentPrinting_Handler
RemoveHandler doc.DocumentSaved, AddressOf DocEventHandlers1.DocEvent_DocumentSaved_Handler
RemoveHandler doc.DocumentSavedAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavedAs_Handler
RemoveHandler doc.DocumentSaving, AddressOf DocEventHandlers1.DocEvent_DocumentSaving_Handler
RemoveHandler doc.DocumentSavingAs, AddressOf DocEventHandlers1.DocEvent_DocumentSavingAs_Handler
RemoveHandler doc.ViewPrinted, AddressOf DocEventHandlers1.DocEvent_ViewPrinted_Handler
RemoveHandler doc.ViewPrinting, AddressOf DocEventHandlers1.DocEvent_ViewPrinting_Handler
End Sub
Public Shared Sub UIAppEvent_ViewActivated_Handler(ByVal sender As [Object], ByVal args As EventArgs)
Dim specArgs As Autodesk.Revit.UI.Events.ViewActivatedEventArgs = TryCast(args, Autodesk.Revit.UI.Events.ViewActivatedEventArgs)
If Not _registered Then
' Only subscribing once!
_app = specArgs.Document.Application
SubscribeForApplication(_app)
_registered = True
End If
End Sub
Public Shared Sub UIAppEvent_ApplicationClosing_Handler(ByVal sender As [Object], ByVal args As EventArgs)
Dim specArgs As Autodesk.Revit.UI.Events.ApplicationClosingEventArgs = TryCast(args, Autodesk.Revit.UI.Events.ApplicationClosingEventArgs)
If _app IsNot Nothing AndAlso _registered Then
UnsubscribeForApplication(_app)
_registered = False
End If
End Sub
Public Shared Sub AppEvent_DocumentCreated_Handler(ByVal sender As [Object], ByVal args As EventArgs)
Dim specArgs As Autodesk.Revit.DB.Events.DocumentCreatedEventArgs = TryCast(args, Autodesk.Revit.DB.Events.DocumentCreatedEventArgs)
SubscribeToDoc(specArgs.Document)
End Sub
Public Shared Sub AppEvent_DocumentOpened_Handler(ByVal sender As [Object], ByVal args As EventArgs)
Dim specArgs As Autodesk.Revit.DB.Events.DocumentOpenedEventArgs = TryCast(args, Autodesk.Revit.DB.Events.DocumentOpenedEventArgs)
SubscribeToDoc(specArgs.Document)
End Sub
Public Shared Sub AppEvent_DocumentClosing_Handler(ByVal sender As [Object], ByVal args As EventArgs)
Dim specArgs As Autodesk.Revit.DB.Events.DocumentClosingEventArgs = TryCast(args, Autodesk.Revit.DB.Events.DocumentClosingEventArgs)
UnsubscribeFromDoc(specArgs.Document)
End Sub
End Class
With the subscriber, it is very straightforward and reliable to subscribe document events in an external application:
Public Function OnStartup(ByVal uiApp As UIControlledApplication) As Result Implements IExternalApplication.OnStartup
_cachedUiCtrApp = uiApp
Try
Dim docEventScrscipber As New DocEventSubscriber(_cachedUiCtrApp) 'Subscribe to all documents in the whole Revit session.
Return Result.Succeeded
Catch ex As Exception
MessageBox.Show(ex.ToString())
Return Result.Failed
End Try
End Function
All these code was created automatically by the RevitAddinWizard in a moment. Enjoy!
Recent Comments