The script that I have put together was just for learning purposes and I have not spent time naming classes / functions / variables in a good way, sorry
so this script asks the user to pick a line (annotation line) and shows a list of views where instances of this line type exist
please do not use on live project as I have not tested the code fully
this is the script
#import libraries
import Autodesk
from Autodesk.Revit.DB import *
from Autodesk.Revit.UI import *
from Autodesk.Revit.UI import IExternalEventHandler, ExternalEvent
from Autodesk.Revit.UI import Selection
from Autodesk.Revit.UI.Selection import *
from Autodesk.Revit.Exceptions import InvalidOperationException
from pyrevit.forms import WPFWindow
from pyrevit import script, HOST_APP, engine, revit
# noinspection PyUnresolvedReferences
from pyrevit import UI
# get current document
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
app = __revit__.Application
uiapp = __revit__
selection = uidoc.Selection
class CustomISelectionFilter(ISelectionFilter):
def AllowElement(self, element):
if type(element) == DetailLine:
return True
class CustomizableEvent:
def __init__(self):
# Create an handler instance and his associated ExternalEvent
custom_handler = _CustomHandler()
custom_handler.customizable_event = self
self.custom_event = UI.ExternalEvent.Create(custom_handler)
# Initialise raise_event variables
self.function_or_method = None
self.args = ()
self.kwargs = {}
def _raised_method(self):
self.function_or_method(*self.args, **self.kwargs)
def raise_event(self, function_or_method, *args, **kwargs):
self.args = args
self.kwargs = kwargs
self.function_or_method = function_or_method
self.custom_event.Raise()
class _CustomHandler(UI.IExternalEventHandler):
"""Subclass of IExternalEventHandler intended to be used in CustomizableEvent class
Input : function or method. Execute input in a IExternalEventHandler"""
def __init__(self):
self.customizable_event = None
# Execute method run in Revit API environment.
# noinspection PyPep8Naming, PyUnusedLocal
def Execute(self, application):
try:
self.customizable_event._raised_method()
except InvalidOperationException:
# If you don't catch this exeption Revit may crash.
print("InvalidOperationException catched")
# noinspection PyMethodMayBeStatic, PyPep8Naming
def GetName(self):
return "Execute an function or method in a IExternalHandler"
customizable_event = CustomizableEvent()
class Lesson10 (WPFWindow):
def __init__(self, xaml_file_name):
WPFWindow.__init__(self, xaml_file_name)
self.linestyle_name=""
self.view_ids = []
self.unique_view_ids={}
self.ShowDialog()
def select_line_inmodel(self):
try:
selected_line_ref = selection.PickObject(ObjectType.Element, CustomISelectionFilter())
selected_line = uidoc.Document.GetElement(selected_line_ref)
selected_linestyle_name = selected_line.LineStyle.Name
self.linestyle_name = selected_linestyle_name
except:
UI.TaskDialog.Show("Operation canceled","Canceled by the user")
#Find views where we have an instance of the selected line style
#Collect all the line types
lines = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Lines)
#filter out the line type and get views that have the selected linestle
for l in lines:
if l.LineStyle.Name == self.linestyle_name:
self.view_ids.append(l.OwnerViewId)
#Create a unique list of view Ids
for i in self.view_ids:
if i in self.unique_view_ids: self.unique_view_ids[i] +=1
else: self.unique_view_ids[i] =1
return self.unique_view_ids
# def get_selected_linestyle(self):
# selected_items = []
# for item in self.UI_ListBox_Materials.ItemsSource:
# if item.IsChecked:
# selected_items.append(item.element)
# return selected_items
def out_put(self):
#Script output
output = script.get_output()
#Header for output
output.print_md("List of all View where we have instance/s of linestyle: {}".format(self.linestyle_name))
print ("Click on a Id of the view to open it...")
# report the views hosting the line style
for key, value in (sorted(self.unique_view_ids.items())):
print('There are {} instances of line style: {} on View:'.format(value, self.linestyle_name) + (doc.GetElement(key).Name) + '{} '.format(output.linkify(key)))
def SelectLineButton_Click(self, sender, e):
self.Hide()
customizable_event.raise_event(self.select_line_inmodel)
self.Show()
def Cancel_button(self, sender, e):
self.Close()
def OK_button(self, sender, e):
self.Close()
self.out_put()
if __name__ == '__main__':
modeless_form = Lesson10("ui.xaml")
and this is the xaml file
<?xml version="1.0" encoding="utf-8"?>
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Lesson_10"
Height="500"
Width="300" WindowStartupLocation="CenterScreen">
<StackPanel Grid.Row="2"
VerticalAlignment="Top"
Margin="10,5,10,5">
<Button
x:Name="SelectLineButton"
Content="Select a line in your model"
Click="SelectLineButton_Click"
Margin="5" />
<TextBlock
Text="Or Select from below list"
FontWeight="Bold"
Margin="0 10"
HorizontalAlignment="Center" />
<ListBox
x:Name="UI_ListBox_Categories"
Height="350"
SelectionMode="Single"
HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox
IsChecked="{Binding IsChecked}">
<TextBlock
Text="{Binding Name}" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition
Width="*" />
<ColumnDefinition
Width="*" />
</Grid.ColumnDefinitions>
<Button
x:Name="OK"
Grid.Column="0"
Margin="5 10 5 10"
Content="Ok"
Click="OK_button" />
<Button
x:Name="Cancel"
Grid.Column="2"
Margin="5 10 5 10"
Content="Cancel"
Click="Cancel_button" />
</Grid>
</StackPanel>
</Window>
the script is work in progress as I am planning to have it show a full list of line types so user can either select it in the view or pick one from list. Hope this help