So thanks to Michael, I have got this running in Sandbox…
# Reference the WPF assemblies
import clr
import sys
import System.Windows
from wpf import *
from System.Threading import Thread, ThreadStart, ApartmentState
clr.AddReference('PresentationFramework')
# Initialization Constants
Window = System.Windows.Window
Application = System.Windows.Application
def appThread():
my_window = Window()
my_window.Show()
thread = Application.Current.Dispatcher.Invoke(appThread)
However in DynamoRevit, it is still chucking an error (presumably due to Revit having 1 thread not a separate dispatch thread.
I found an interesting thing here… https://pythoncvc.net/?p=247 and doctored it to get it running in Dynamo Revit
import clr
# Reference the WPF assemblies
import sys
import System.Windows
from wpf import *
clr.AddReference('PresentationFramework')
clr.AddReference('RevitAPI')
clr.AddReference('RevitAPIUI')
clr.AddReference('RevitServices')
# noinspection PyUnresolvedReferences
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
# noinspection PyUnresolvedReferences
from Autodesk.Revit.DB import Transaction
# noinspection PyUnresolvedReferences
from Autodesk.Revit.Exceptions import InvalidOperationException
from RevitServices import *
from RevitServices.Persistence import DocumentManager
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI.Selection import *
doc = DocumentManager.Instance.CurrentDBDocument
uidoc = DocumentManager.Instance.CurrentUIApplication.ActiveUIDocument
# Initialization Constants
Window = System.Windows.Window
# Simple function we want to run
def delete_elements():
t = Transaction(doc, "Failing script")
t.Start()
for elid in uidoc.Selection.GetElementIds():
print elid
doc.Delete(elid)
t.Commit()
# Create a subclass of IExternalEventHandler
class SimpleEventHandler(IExternalEventHandler):
"""
Simple IExternalEventHandler sample
"""
# __init__ is used to make function from outside of the class to be executed by the handler. \
# Instructions could be simply written under Execute method only
def __init__(self, do_this):
self.do_this = do_this
# Execute method run in Revit API environment.
def Execute(self, uiapp):
try:
self.do_this()
except InvalidOperationException:
# If you don't catch this exeption Revit may crash.
print "InvalidOperationException catched"
def GetName(self):
return "simple function executed by an IExternalEventHandler in a Form"
# Now we need to make an instance of this handler. Moreover, it shows that the same class could be used to for
# different functions using different handler class instances
simple_event_handler = SimpleEventHandler(delete_elements)
# We now need to create the ExternalEvent
ext_event = ExternalEvent.Create(simple_event_handler)
# A simple WPF form used to call the ExternalEvent
class ModelessForm(Window):#WPFWindow):
"""
Simple modeless form sample#
"""
def __init__(self):
Window.__init__(self)
self.Title = "Hello World"
self.Show()
def delete_click(self, sender, e):
# This Raise() method launch a signal to Revit to tell him you want to do something in the API context
ext_event.Raise()
# Let's launch our beautiful and useful form !
modeless_form = ModelessForm()