Next button node or script

Hi,

a Python solution using IExternalEventHandler and a ListView in a non-modal Window(wpf)

zoomtodoors

code Python (compatible with PythonNet3 and IronPython3)
import sys
import clr
import System
from System.Collections.Generic import List, IList, Dictionary
from System import  EventHandler, Uri
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB

clr.AddReference('RevitAPIUI')
import Autodesk.Revit.UI as RUI
from Autodesk.Revit.UI import *

#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument

clr.AddReference("System.Core")
clr.ImportExtensions(System.Linq)

clr.AddReference("System.Xml")
clr.AddReference("PresentationFramework")
clr.AddReference("System.Xml")
clr.AddReference("PresentationCore")
clr.AddReference("System.Windows")
import System.Windows.Controls 
from System.Windows.Controls import *
from System.IO import StringReader
from System.Xml import XmlReader
from System.Windows import LogicalTreeHelper 
from System.Windows.Markup import XamlReader, XamlWriter
from System.Windows import Window, Application

import time
import traceback

class MainForm(Window):
    string_xaml = '''
    <Window 
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            Title="My WPF Window" Height="500" Width="350">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <!-- ListView -->
                <ListView x:Name="ItemsListView" Grid.Row="0" Margin="10" >
                    <ListView.View>
                        <GridView>
                            <GridViewColumn Header="Elements (Double Click to Zoom)" Width="300" DisplayMemberBinding="{Binding Name}"/>
                        </GridView>
                    </ListView.View>
                </ListView>
        
                <!-- Button -->
                <Button x:Name="ButtonOK" Grid.Row="1" Content="OK" Margin="10" Height="30" Width="100" HorizontalAlignment="Center"/>
            </Grid>
        </Window>'''
  
    def __init__(self, lst_elem):
        super().__init__() # remove or comment this line with IronPython2
        self.lst_elem = lst_elem
        xr = XmlReader.Create(StringReader(MainForm.string_xaml))
        root= XamlReader.Load(xr) 
        for prop_info in root.GetType().GetProperties():
            if prop_info.CanWrite:
                try:
                    setattr(self, prop_info.Name, prop_info.GetValue(root)) 
                except Exception as ex:
                    print(ex, prop_info.Name) # synthax modified for all engine IronPython2, IronPython3, PythonNet3
        #
        self.ext_eventZoom = None
        self.elem = None
        self.bbx_to_Zoom = None
        self.InitializeComponent()
        
    def InitializeComponent(self):
        self.ListViewElement = LogicalTreeHelper.FindLogicalNode(self, "ItemsListView")
        self.ListViewElement.ItemsSource  = self.lst_elem
        self.ListViewElement.MouseDoubleClick += self.ListView_MouseDoubleClick
        #
        self.ButtonOK = LogicalTreeHelper.FindLogicalNode(self, "ButtonOK") 
        self.ButtonOK.Click += self.ButtonOkClick

    def ListView_MouseDoubleClick(self, sender, e):
        try:
            self.elem = e.OriginalSource.DataContext
            print(self.elem)
            self.bbx_to_Zoom = self.elem.get_BoundingBox(None)
            self.ext_eventZoom.Raise()
        except Exception as ex:
            print(traceback.format_exc())
        
    def ButtonOkClick(self, sender, e):
        try:
            self.ext_eventZoom.Dispose()
            self.Close()
        except Exception as ex:
            print(traceback.format_exc())
            
class ModExternalEventZoom(IExternalEventHandler):
    __namespace__ = "ModExternalEventZoom_SDy8" 
    def __init__(self, objform):
        super().__init__() # remove or comment this line with IronPython2
        self.objform = objform
        
    def Execute(self, _uiap):        
        _uidoc = _uiap.ActiveUIDocument
        _doc = _uidoc.Document
        _app = _uiap.Application
        _view = _doc.ActiveView
        filterFunc = lambda x : not x.IsTemplate and x.ViewType == ViewType.ThreeD and (x.Name == "{3D - " + _app.Username  + "}" or x.Name == "{3D}")
        threeViewD = FilteredElementCollector(_doc).OfCategory(BuiltInCategory.OST_Views).WhereElementIsNotElementType()\
                                                    .FirstOrDefault(System.Func[DB.Element, System.Boolean](filterFunc))
        #processing
        if  self.objform.bbx_to_Zoom is not None:    
            pt1 = self.objform.bbx_to_Zoom.Min
            pt2 = self.objform.bbx_to_Zoom.Max    
            tx = Transaction(_doc)
            tx.Start("MyEventZoom")                
                    
            try:
                threeViewD.SetSectionBox(self.objform.bbx_to_Zoom)
                _uidoc.Selection.SetElementIds(List[ElementId]([self.objform.elem.Id]))
            except Exception as ex:
                print(traceback.format_exc()) 
            tx.Commit()     
            _uidoc.RequestViewChange(threeViewD)
            try:
                uiviews = _uidoc.GetOpenUIViews()
                uiview = next((x for x in uiviews if x.ViewId == threeViewD.Id), None)
                if uiview is not None:    
                    uiview.ZoomAndCenterRectangle(pt1, pt2)
            except Exception as ex:
                print(traceback.format_exc())

    def GetName(self):
        return "ModExternalEventZoom"        
            
# create UI
lst_elem = UnwrapElement(IN[0])
TransactionManager.Instance.ForceCloseTransaction()
winObj = MainForm(lst_elem)

obj_handlerZoom = ModExternalEventZoom(winObj)    
ext_eventZoom = ExternalEvent.Create(obj_handlerZoom)	
# set attribute event
winObj.ext_eventZoom = ext_eventZoom

winObj.Show()

It will need to be adapted if
-you use ElementIds as input instead of Elements
-you use IronPython2 (I advise against using CPython3 for this example)

use AI for code comprehension if necessary

8 Likes