Well, I still have not solved the original issue, but I found what should have been an obvious workaround. The pop-up dialog that triggers the unresponsiveness can be avoided by opening the element’s owner view before showing the element. That way, there is no need to dismiss the dialog in the first place.
For anyone following who wants to use this code, here are the files:
bundle.yaml file:
engine:
persistent: true
title: "Fix Room\nTags"
tooltip: Finds errant room tags and allows the user to fix them.
author: Frank Loftus
script.py file:
# dependencies
import clr
clr.AddReference('System.Windows.Forms')
clr.AddReference('IronPython.Wpf')
# Import from pyrevit
from pyrevit import UI
from pyrevit import script
from pyrevit.forms import WPFWindow
from pyrevit.revit import Transaction as pyrevit_transaction
##from pyrevit.revit import doc # Alternative way to access doc through pyrevit
xamlfile = script.get_bundle_file('ui.xaml') # find the path of ui.xaml
# import WPF creator and base Window
import wpf
from System import Windows
from System import EventHandler as WinEventHandler
# import python system module
import sys
'''
# Import ctypes for access to SetForegroundWindow(). No longer used.
import ctypes
'''
# Import Revit API objects
clr.AddReference("RevitAPI")
from Autodesk.Revit.DB import ViewType, Transaction, ElementId, FilteredElementCollector, BuiltInCategory, BuiltInParameter, Element, RevitLinkInstance
from Autodesk.Revit.DB.Architecture import RoomTag, Room
from Autodesk.Revit.UI import UIDocument, Selection, TaskDialog, TaskDialogResult, IExternalEventHandler, ExternalEvent
from Autodesk.Revit.UI.Events import DialogBoxShowingEventArgs, TaskDialogShowingEventArgs
from Autodesk.Revit.UI.UIDocument import GetOpenUIViews, ActiveView, ShowElements
from Autodesk.Revit.Exceptions import InvalidOperationException
# Import .NET List
from System.Collections.Generic import List
# Global variables
script_name = 'Fix Room Tags'
GLOBAL_DEBUG = False
# Toggleable print function. Turn on to debug.
def p(*to_print):
if GLOBAL_DEBUG:
for item in to_print:
print item
# Setup doc
uiapp = __revit__
uidoc = __revit__.ActiveUIDocument
doc = __revit__.ActiveUIDocument.Document
def dismiss_dialog (sender, event_args): #### No longer used.
id_ok = 1
try:
p('type(event_args):', type(event_args))
if isinstance(event_args, TaskDialogShowingEventArgs):
p('dismissing dialog {}. Cancellable: {}'.format(event_args.DialogId, event_args.Cancellable))
result = event_args.OverrideResult(id_ok)
p('dismissed:', result)
except Exception as ex:
# Hacky way to catch and print exceptions within:
print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(ex).__name__, ex)
print(sys.exc_info()[-1].tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_next.tb_next.tb_lineno)
def show_element_OBSOLETE(element): #### No longer used
if element:
global uidoc
# Use a windows EventHandler to dismiss the pop-up dialog upon ShowElements()
dialog_event_handler = WinEventHandler[DialogBoxShowingEventArgs](dismiss_dialog)
uiapp.DialogBoxShowing += dialog_event_handler
uidoc.ShowElements(element)
uiapp.DialogBoxShowing -= dialog_event_handler
def show_element(element):
if element:
global uidoc
# Acquire tag's OwnerView and open it before ShowElements() to avoid pop-up dialog
active_view = uidoc.ActiveView
owner_view_id = element.OwnerViewId
if active_view.Id != owner_view_id:
owner_view = doc.GetElement(owner_view_id)
uidoc.ActiveView = owner_view
uidoc.ShowElements(element)
# Create a subclass of IExternalEventHandler
class EventHandler(IExternalEventHandler):
def __init__(self, func_to_run):
self.func = func_to_run
def Execute(self, uiapp):
try:
self.func()
except Exception as ex:
# Hacky way to catch and print exceptions within Execute():
print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(ex).__name__, ex)
print(sys.exc_info()[-1].tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_next.tb_lineno)
print(sys.exc_info()[-1].tb_next.tb_next.tb_next.tb_next.tb_next.tb_lineno)
def GetName(self):
return "simple function executed by an IExternalEventHandler in a Form"
class ListItem:
def __init__(self, elem):
# Initial properties
self.elem = elem
self.elem_id = elem.Id
self.elem_id_str = self.elem_id.ToString()
self.status = self.status
self.owner_view_id = elem.OwnerViewId
self.owner_view = doc.GetElement(self.owner_view_id)
self.owner_view_name = self.owner_view.Name
self.room_number = self.room.Number if self.room else ''
self.room_name = self.room.get_Parameter(BuiltInParameter.ROOM_NAME).AsString() if self.room else 'No Room'
@property
def status(self):
if self.elem.IsOrphaned:
return '(Orphaned)'
elif not self.elem.IsInRoom:
return '(Misplaced)'
else:
return False
@property
def room(self):
if not self.elem.IsOrphaned:
if self.elem.IsTaggingLink:
linked_element_id = self.elem.TaggedRoomId.LinkedElementId
link_instance_id = self.elem.TaggedRoomId.LinkInstanceId
link_instance = doc.GetElement(link_instance_id)
link_doc = link_instance.GetLinkDocument()
linked_room = link_doc.GetElement(linked_element_id)
return linked_room
else:
tagged_local_room = doc.GetElement(self.elem.TaggedLocalRoomId)
return tagged_local_room
else: p('tag is orphaned. cannot find tagged room.')
@property
def display_string(self):
return '{}, {}, {} {}, View: {}'.format(self.status, self.elem_id_str, self.room_name, self.room_number, self.owner_view_name)
class Display:
def __init__(self, form, model=None, view=None):
self.form = form
self.model = model
self.view = view
def refresh_model(self):
self.model = self.form.list_items_in_model
self.form.listbox_entire_model.ItemsSource = [list_item.display_string for list_item in self.model]
def refresh_view(self):
self.view = self.form.list_items_in_view
self.form.listbox_current_view.ItemsSource = [list_item.display_string for list_item in self.view]
def set_model(self, list_items):
self.model = list_items
self.form.listbox_entire_model.ItemsSource = [list_item.display_string for list_item in list_items]
def set_view(self, list_items):
self.view = list_items
self.form.listbox_current_view.ItemsSource = [list_item.display_string for list_item in list_items]
# WPF form used to call the ExternalEvents
class ModelessForm(WPFWindow):
def __init__(self, xaml_file_name):
WPFWindow.__init__(self, xaml_file_name)
self.current_tag_index = 0
self.recentered_list_item = None
self.recentered_list_items = None
self.current_tag = None
self.display = Display(self)
# Create instance of handler, then instance of event for each button/command
self.refresh_window_handler = EventHandler(self.refresh_window)
self.refresh_window_event_instance = ExternalEvent.Create(self.refresh_window_handler)
self.listbox_current_view_selection_change_handler = EventHandler(self.listbox_current_view_selection_change)
self.listbox_current_view_selection_change_event_instance = ExternalEvent.Create(self.listbox_current_view_selection_change_handler)
self.listbox_current_view_got_focus_handler = EventHandler(self.listbox_current_view_got_focus)
self.listbox_current_view_got_focus_event_instance = ExternalEvent.Create(self.listbox_current_view_got_focus_handler)
self.recenter_selected_tag_handler = EventHandler(self.recenter_selected_tag)
self.recenter_selected_tag_event_instance = ExternalEvent.Create(self.recenter_selected_tag_handler)
self.delete_selected_tag_handler = EventHandler(self.delete_selected_tag)
self.delete_selected_tag_event_instance = ExternalEvent.Create(self.delete_selected_tag_handler)
self.listbox_entire_model_selection_change_handler = EventHandler(self.listbox_entire_model_selection_change)
self.listbox_entire_model_selection_change_event_instance = ExternalEvent.Create(self.listbox_entire_model_selection_change_handler)
self.listbox_entire_model_got_focus_handler = EventHandler(self.listbox_entire_model_got_focus)
self.listbox_entire_model_got_focus_event_instance = ExternalEvent.Create(self.listbox_entire_model_got_focus_handler)
self.recenter_all_tags_in_view_handler = EventHandler(self.recenter_all_tags_in_view)
self.recenter_all_tags_in_view_event_instance = ExternalEvent.Create(self.recenter_all_tags_in_view_handler)
self.delete_all_orphans_in_view_handler = EventHandler(self.delete_all_orphans_in_view)
self.delete_all_orphans_in_view_event_instance = ExternalEvent.Create(self.delete_all_orphans_in_view_handler)
self.delete_room_tags_not_visible_in_any_view_handler = EventHandler(self.delete_room_tags_not_visible_in_any_view)
self.delete_room_tags_not_visible_in_any_view_event_instance = ExternalEvent.Create(self.delete_room_tags_not_visible_in_any_view_handler)
self.next_tag_handler = EventHandler(self.next_tag)
self.next_tag_event_instance = ExternalEvent.Create(self.next_tag_handler)
self.previous_tag_handler = EventHandler(self.previous_tag)
self.previous_tag_event_instance = ExternalEvent.Create(self.previous_tag_handler)
# Populate ListBox with RoomTags from model
self.display.refresh_model()
self.display.refresh_view()
# Populate item quantities
self.textblock_quantity_in_model.Text = self.quantity_in_model_str
self.textblock_view_name.Text = self.active_ui_view.Name
self.textblock_quantity_in_view.Text = self.quantity_in_view_str
# Show modeless window
self.show_self()
# Properties
@property
def active_ui_view(self):
return uidoc.ActiveView
@property
def link_instances(self): #### Not used currently.
result = FilteredElementCollector(doc).OfClass(RevitLinkInstance)
p('linked_models:', result)
return result
@property
def link_documents(self): #### Not used currently.
if self.link_instances:
result = [instance.GetLinkDocument() for instance in self.link_instances]
result_cleaned = [document for document in result if document is not None]
p('link_documents:', result_cleaned)
return result_cleaned
else: p('No link instances. Cannot create link_documents.')
@property
def link_titles(self): #### Not used currently.
if self.link_documents:
result = [document.Title for document in self.link_documents]
p('link_titles:', result)
return result
else: p('No link documents. Cannot create link_titles.')
@property
def room_tags_in_model(self):
result = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RoomTags).WhereElementIsNotElementType()
p('room_tags_in_model:', result)
if result: return result
else: p('No room tags in model.')
@property
def room_tag_owner_view_ids_in_model_set(self):
if self.room_tags_in_model:
result = set([tag.OwnerViewId for tag in self.room_tags_in_model])
p('room_tag_owner_view_ids_in_model_set:', result)
return result
else: p('No room tags in model. Cannot make room_tag_owner_view_ids_in_model_set.')
@property
def room_tags_visible_in_model(self):
room_tags_visible_in_model = List[Element]()
if self.room_tag_owner_view_ids_in_model_set:
for owner_view_id in self.room_tag_owner_view_ids_in_model_set:
room_tags_visible_in_view = FilteredElementCollector(doc, owner_view_id).OfCategory(BuiltInCategory.OST_RoomTags).WhereElementIsNotElementType().ToElements()
room_tags_visible_in_model.AddRange(room_tags_visible_in_view)
p('room_tags_visible_in_model:', [tag.Id.ToString() for tag in room_tags_visible_in_model])
return room_tags_visible_in_model
else: p('No room_tag_owner_view_ids_in_model_set. Cannot make room_tags_visible_in_model')
@property
def room_tag_ids_not_visible_in_any_view(self):
room_tags_in_model = self.room_tags_in_model
if room_tags_in_model:
room_tag_ids_in_model = [tag.Id.IntegerValue for tag in room_tags_in_model]
room_tag_ids_in_model_set = set(room_tag_ids_in_model)
p('room_tags_in_model_set:', [tag_id for tag_id in room_tag_ids_in_model_set])
if self.room_tags_visible_in_model:
room_tags_visible_in_model_list = self.room_tags_visible_in_model
room_tag_ids_visible_in_model = [tag.Id.IntegerValue for tag in room_tags_visible_in_model_list]
room_tag_ids_visible_in_model_set = set(room_tag_ids_visible_in_model)
set_diff = room_tag_ids_in_model_set.difference(room_tag_ids_visible_in_model_set)
result = [ElementId(tag_id_string) for tag_id_string in set_diff]
p('room_tags_not_visible_in_any_view:', [tag_id.IntegerValue for tag_id in result])
return result
else: p('no room tags visible in model. cannot make room_tags_not_visible_in_any_view')
else: p('no room tags in model. cannot make room_tags_not_visible_in_any_view')
@property
def room_tags_in_view(self):
result = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_RoomTags).WhereElementIsNotElementType().OwnedByView(self.active_ui_view.Id)
p('room_tags_in_view:', result)
return result
@property
def orphaned_room_tags_in_model(self):
result = [room_tag for room_tag in self.room_tags_in_model if room_tag.IsOrphaned]
p('orphaned_room_tags_in_model:', result)
return result
@property
def misplaced_room_tags_in_model(self):
result = [room_tag for room_tag in self.room_tags_in_model if not room_tag.IsInRoom]
p('misplaced_room_tags_in_model:', result)
return result
@property
def orphaned_or_misplaced_room_tags_in_model(self):
result = [room_tag for room_tag in self.room_tags_in_model if room_tag.IsOrphaned or not room_tag.IsInRoom]
p('orphaned_or_misplaced_room_tags_in_model:', [elem.Id for elem in result])
return result
@property
def list_items_in_model(self):
result = [ListItem(room_tag) for room_tag in self.room_tags_in_model if room_tag.IsOrphaned or not room_tag.IsInRoom]
p('orphaned_or_misplaced_room_tags_in_model:', [list_item.elem.Id for list_item in result])
return result
@property
def display_strings_in_model(self):
return [list_item.display_string for list_item in self.display.model]
@property
def quantity_in_model(self):
result = len(self.orphaned_or_misplaced_room_tags_in_model)
p('quantity_in_model:', result)
return result
@property
def quantity_in_model_str(self):
return str(self.quantity_in_model)
@property
def tag_ids_in_model(self):
result = [tag.Id for tag in self.orphaned_or_misplaced_room_tags_in_model]
p('tag_ids_in_model:', result)
return result
@property
def recentered_tag_ids(self):
return [tag.Id for tag in self.recentered_tags]
@property
def recentered_list_item_ids(self):
return [list_item.elem.Id for list_item in self.recentered_list_items]
@property
def recentered_display_strings(self):
return [list_item.display_string for list_item in self.recentered_list_items]
@property
def orphaned_in_view(self):
result = [room_tag for room_tag in self.room_tags_in_view if room_tag.IsOrphaned]
p('orphaned_in_view:', [elem.Id for elem in result])
return result
@property
def misplaced_in_view(self):
result = [room_tag for room_tag in self.room_tags_in_view if not room_tag.IsInRoom]
p('misplaced_in_view:', [elem.Id for elem in result])
return result
@property
def orphaned_or_misplaced_room_tags_in_view(self):
result = [room_tag for room_tag in self.room_tags_in_view if room_tag.IsOrphaned or not room_tag.IsInRoom]
p('orphaned_or_misplaced_room_tags_in_view:', [elem.Id for elem in result])
return result
@property
def list_items_in_view(self):
result = [ListItem(room_tag) for room_tag in self.room_tags_in_view if room_tag.IsOrphaned or not room_tag.IsInRoom]
p('orphaned_or_misplaced_room_tags_in_view:', [list_item.elem.Id for list_item in result])
return result
@property
def display_strings_in_view(self):
return [list_item.display_string for list_item in self.display.view]
@property
def tag_ids_in_current_view(self):
result = [tag.Id for tag in self.orphaned_or_misplaced_room_tags_in_view]
p('tag_ids_in_current_view:', result)
return result
@property
def quantity_in_view(self):
result = len(self.orphaned_or_misplaced_room_tags_in_view)
p('quantity_in_view:', result)
return result
@property
def quantity_in_view_str(self):
return str(self.quantity_in_view)
# Methods
'''
def regain_focus(self): #### No longer used.
ctypes.windll.user32.SetForegroundWindow(self.as_foreground_window)
'''
def show_self(self):
self.Show()
'''
# Set self as foreground window. No longer used.
self.as_foreground_window = ctypes.windll.user32.GetForegroundWindow()
p('foreground window:', self.as_foreground_window)
'''
def recenter_tag(self, tag):
if not tag: p('no input tag. cannot recenter_tag()')
else: # If tag exists:
if tag.IsOrphaned: p('tag is orphaned. cannot recenter_tag()')
else: # If tag can be recentered:
if tag.IsTaggingLink:
linked_element_id = tag.TaggedRoomId.LinkedElementId
link_instance_id = tag.TaggedRoomId.LinkInstanceId
link_instance = doc.GetElement(link_instance_id)
link_instance_transform = link_instance.GetTransform()
link_doc = link_instance.GetLinkDocument()
linked_room = link_doc.GetElement(linked_element_id)
room_location = linked_room.Location
tag.Location.Point = link_instance_transform.OfPoint(room_location.Point)
self.recentered_list_item = ListItem(tag)
else: # If tag is tagging local room in host model:
tagged_local_room = doc.GetElement(tag.TaggedLocalRoomId)
room_location = tagged_local_room.Location
tag.Location.Point = room_location.Point
self.recentered_list_item = ListItem(tag)
# Methods to call via external event
def refresh_window(self):
button_name = 'refresh_window'
new_window = ModelessForm("ui.xaml")
self.Close()
p('{} succeeded'.format(button_name))
def listbox_entire_model_selection_change(self):
button_name = 'listbox_entire_model_selection_change'
selected_index = self.listbox_entire_model.SelectedIndex
if selected_index > -1:
self.current_tag = self.display.model[selected_index].elem
if len(self.display.model) > 0:
show_element(self.current_tag)
self.refresh_listboxes_and_quantities()
self.current_tag_index = selected_index
p('{} succeeded'.format(button_name))
else: p('selected_index not > -1. Likely no list items in listbox.')
def listbox_entire_model_got_focus(self):
self.listbox_entire_model_selection_change()
def listbox_current_view_selection_change(self):
button_name = 'listbox_current_view_selection_change'
selected_index = self.listbox_current_view.SelectedIndex
if selected_index > -1:
self.current_tag = self.display.view[selected_index].elem
if len(self.display.view) > 0:
show_element(self.current_tag)
elems_in_model = [item.elem_id for item in self.display.model]
self.current_tag_index = elems_in_model.index(self.current_tag.Id)
p('{} succeeded'.format(button_name))
else: p('selected_index not > -1. Likely no list items in listbox.')
def listbox_current_view_got_focus(self):
self.listbox_current_view_selection_change()
def recenter_selected_tag(self):
button_name = 'recenter_selected_tag'
if self.current_tag:
if not self.current_tag.IsOrphaned:
with pyrevit_transaction("Recenter room tag"):
self.recenter_tag(self.current_tag)
show_element(self.recentered_list_item.elem)
p('{} succeeded'.format(button_name))
else: p('no current_tag. cannot recenter_selected_tag()')
def refresh_listboxes(self):
self.display.refresh_model()
self.display.refresh_view()
def refresh_quantities(self):
self.textblock_quantity_in_model.Text = self.quantity_in_model_str
self.textblock_quantity_in_view.Text = self.quantity_in_view_str
def refresh_active_view_text(self):
self.textblock_view_name.Text = self.active_ui_view.Name
def refresh_listboxes_and_quantities(self):
self.refresh_listboxes()
self.refresh_quantities()
self.refresh_active_view_text()
def delete_selected_tag(self):
if self.current_tag:
button_name = 'delete_selected_tag'
p('deleting selected_tag {}'.format(self.current_tag.Id))
with pyrevit_transaction("Delete room tag"):
doc.Delete(self.current_tag.Id)
self.current_tag = None
self.refresh_listboxes_and_quantities()
p('{} succeeded'.format(button_name))
else: p('no current tag. cannot delete_selected_tag()')
def recenter_all_tags_in_view(self):
misplaced_in_view = self.misplaced_in_view
if misplaced_in_view:
button_name = 'recenter_all_tags_in_view'
recentered_list_items = []
with pyrevit_transaction("Recenter all room tags in view"):
for tag in misplaced_in_view:
self.recenter_tag(tag)
recentered_list_items.append(ListItem(tag))
self.recentered_list_items = recentered_list_items
self.display.set_view(self.recentered_list_items)
if self.display.view: show_element(self.display.view[0].elem)
p('{} succeeded'.format(button_name))
else: p('no misplaced tags in view. cannot recenter_all_tags_in_view()')
def delete_all_orphans_in_view(self):
button_name = 'delete_all_orphans_in_view'
with pyrevit_transaction("Delete orphaned room tags in view"):
for tag in self.orphaned_in_view:
doc.Delete(tag.Id)
self.refresh_listboxes_and_quantities()
p('{} succeeded'.format(button_name))
def delete_room_tags_not_visible_in_any_view(self):
button_name = 'delete room tags not visible in any view'
if self.room_tag_ids_not_visible_in_any_view:
with pyrevit_transaction("Delete room tags not visible in any view"):
for tag_id in self.room_tag_ids_not_visible_in_any_view:
doc.Delete(tag_id)
self.refresh_listboxes_and_quantities()
p('{} succeeded'.format(button_name))
else: p('No self.room_tag_ids_not_visible_in_any_view. Cannot delete_room_tags_not_visible_in_any_view()')
def next_tag(self):
button_name = 'next_tag'
if self.current_tag_index < len(self.display.model) - 1:
self.current_tag_index += 1
p('Current Tag Index: ', self.current_tag_index)
show_element(self.display.model[self.current_tag_index].elem)
self.refresh_listboxes_and_quantities()
p('{} succeeded'.format(button_name))
else: p('There is no next tag to show.')
def previous_tag(self):
button_name = 'previous_tag'
if self.current_tag_index >= 1 < len(self.display.model):
self.current_tag_index -= 1
p('Current Tag Index: ', self.current_tag_index)
show_element(self.display.model[self.current_tag_index].elem)
self.refresh_listboxes_and_quantities()
p('{} succeeded'.format(button_name))
else: p('There is no previous tag to show.')
# Events to call from xaml UI
def close_window(self, sender, args):
self.Close()
def refresh_window_event(self, sender, args):
self.refresh_window_event_instance.Raise()
def listbox_entire_model_selection_change_event(self, sender, args):
self.listbox_entire_model_selection_change_event_instance.Raise()
def listbox_entire_model_got_focus_event(self, sender, args):
self.listbox_entire_model_got_focus_event_instance.Raise()
def listbox_current_view_selection_change_event(self, sender, args):
self.listbox_current_view_selection_change_event_instance.Raise()
def listbox_current_view_got_focus_event(self, sender, args):
self.listbox_current_view_got_focus_event_instance.Raise()
def recenter_selected_tag_event(self, sender, args):
self.recenter_selected_tag_event_instance.Raise()
def delete_selected_tag_event(self, sender, args):
self.delete_selected_tag_event_instance.Raise()
def recenter_all_tags_in_view_event(self, sender, args):
self.recenter_all_tags_in_view_event_instance.Raise()
def delete_all_orphans_in_view_event(self, sender, args):
self.delete_all_orphans_in_view_event_instance.Raise()
def delete_room_tags_not_visible_in_any_view_event(self, sender, args):
self.delete_room_tags_not_visible_in_any_view_event_instance.Raise()
def next_tag_event(self, sender, args):
self.next_tag_event_instance.Raise()
def previous_tag_event(self, sender, args):
self.previous_tag_event_instance.Raise()
# Instantiate the form
modeless_form = ModelessForm("ui.xaml")
ui.xaml file:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:av="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib" mc:Ignorable="av"
Title="Fix Room Tags" ResizeMode="NoResize" SizeToContent="WidthAndHeight" Background="WhiteSmoke" BorderBrush="#FF89AF98" Topmost="True">
<StackPanel x:Name="main_stackpanel" Margin="10">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<StackPanel Orientation="Vertical" Margin="0,0,10,0">
<!--<ComboBox x:Name="select_arch_model_combo_box" SelectionChanged="select_arch_model_event" Text="Select Architectural Model" Background="#FF89AF98" Foreground="Black" MinWidth="155" Margin="0,0,0,10">
</ComboBox>-->
<Button x:Name="delete_room_tags_not_visible_in_any_view_button" Click="delete_room_tags_not_visible_in_any_view_event" Content="Delete room tags not visible in any view" Padding="5,1,5,1" HorizontalContentAlignment="Left" Margin="0,1,0,11"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBlock Text="Errant tags in entire model:" Padding="1,0,5,0" Margin="0,0,0,5" />
<TextBlock x:Name="textblock_quantity_in_model" Text="#" Padding="5,0,5,0" Margin="0,0,0,5" />
</StackPanel>
<ListBox x:Name="listbox_entire_model" GotFocus="listbox_entire_model_got_focus_event" SelectionChanged="listbox_entire_model_selection_change_event" Margin="0,0,0,10" Height="100" />
<Button x:Name="recenter_selected_tag_button" Click="recenter_selected_tag_event" Content="Re-center Selected Tag" HorizontalContentAlignment="Left" Padding="5,1,1,1" />
<Button x:Name="delete_selected_tag_button" Click="delete_selected_tag_event" Content="Delete Selected Tag" HorizontalContentAlignment="Left" Padding="5,1,1,1" />
</StackPanel>
<StackPanel Orientation="Vertical">
<Button x:Name="refresh_button_Copy" Click="refresh_window_event" Content="Refresh" Padding="5,1,5,1" HorizontalContentAlignment="Right" Margin="0,1,0,11"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBlock Text="In current view:" Padding="1,0,5,0" Margin="0,0,0,5" />
<TextBlock x:Name="textblock_view_name" Text="Current View Name" Padding="5,0,5,0" Margin="0,0,0,5" />
<TextBlock x:Name="textblock_quantity_in_view" Text="#" Padding="5,0,5,0" Margin="0,0,0,5" />
</StackPanel>
<ListBox x:Name="listbox_current_view" GotFocus="listbox_current_view_got_focus_event" SelectionChanged="listbox_current_view_selection_change_event" Margin="0,0,0,10" Height="100" >
</ListBox>
<Button Content="Re-center All Tags in View" Click="recenter_all_tags_in_view_event" HorizontalContentAlignment="Right" Padding="1,1,5,1" />
<Button Content="Delete All Orphans in View" Click="delete_all_orphans_in_view_event" HorizontalContentAlignment="Right" Padding="1,1,5,1" />
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,10,0,0" HorizontalAlignment="Right">
<Button x:Name="previous_tag_button" Content="Previous Tag" Height="35" Click="previous_tag_event" Background="#FF89AF98" Foreground="#FF071E42" FontSize="20" BorderThickness="0,0,0,4" VerticalAlignment="Bottom" HorizontalAlignment="Left" Margin="0,0,10,0" Padding="5,1,5,1" VerticalContentAlignment="Top" >
<Button.BorderBrush>
<SolidColorBrush Color="#FF609274" Opacity="1"/>
</Button.BorderBrush>
</Button>
<Button x:Name="next_tag_button" Content="Next Tag" Height="35" Click="next_tag_event" Background="#FF89AF98" Foreground="#FF071E42" FontSize="20" BorderThickness="0,0,0,4" VerticalAlignment="Bottom" HorizontalAlignment="Right" Padding="5,1,5,1" VerticalContentAlignment="Top" >
<Button.BorderBrush>
<SolidColorBrush Color="#FF609274" Opacity="1"/>
</Button.BorderBrush>
</Button>
</StackPanel>
</StackPanel>
</Window>
Put those 3 files in a pyRevit pushbutton and you should be good to go. I would also welcome any suggestions to improve the code.