Learn about Advanced Selection technique
How to use ISelectionFilter class in API
How to create custom criteria for selection
Are you Ready?
Advanced Revit API Selection
Alright, you know how basic Selection works in Revit API.
Now it's time to go a step deeper and learn about advanced selection. There is a way to limit what can be selected when you prompt user to select something. This will greatly improve user experience and avoid a lot of unwanted bugs in the process.
And for that we need to use ISelectionFilter Interface.
Revit API Docs - ISelectionFilter
Let's start with Revit API Documentation.
As you remember, when we explored methods in Selection Class, we saw that some methods can take ISelectionFilter as an argument.
It's available for PickObject, PickObjects and PickElementsByRectangle.
ISelectionFilter - is an Interface.
So it menas we need to create a class based on that to inherit all necessary functionality.
Then we can override pre-written methods with our custom logic so it works correctly.
💡An Interface is like a blueprint for a class, specifying mandatory functionalities without any implementation. By implementing an interface, a class gains certain functionality, while still having the flexibility to customize these functions to suit its needs.
Pre-Written Methods
If you are going to have a look in ISelectionFilter methods, you will see that there are 2 methods, that we can override.
ISelectionFilter Example
Let's start with an example just to get an idea of how it works.
Here is the provided example in C#:
Let's translate it to python so it's easier to explore. You can follow these simple steps to make it Python.
Remove curly braces {}
Remove semi-colons ;
Remove new keywords
Remove Type Hinting
Make sure True/False are capitalized.
Use def for defining function
Use python syntax for class + inheritance
How it works?
It's actually much simpler than you think. Focus on AllowElement method.
You can see that it has an element argument which refers to elements in Revit project. We can use it to create any checks we want and then we return True to allow selection or False to disallow it.
In the example they check if elem.Category.Name
is 'Mass'
. And to be honest that's a very bad example! You should not use string names to check Category, instead use BuiltInCategory as it's more reliable way to check it.
Let's create a new one from scratch.
Simplify Class
I'm going to create a new filter that will check if element has BuiltInCategory.OST_Walls
So here is my new class:
To use it, we need to select a method with ISelectionFilter as an argument and provide an instance of our class. And then it will apply the filter logic during selection.
Let's use PickObjects(objectType, iSelectionFilter) method.
🔥And now you can see that we can only select Walls and nothing else!
Now you can change the logic and try selecting other elements like OST_Windows
for example.
Why we override methods?
Interfaces are like blueprints for classes.
In reality they have a lot more functionality hidden from us, and to access this functionality we need to use pre-written methods.
In our case, we've overridden AllowElement method.
We have to use the same argument types as provided in the documentation. In our case elem argument represents an Element type.
This argument element, will represent all elements that might be allowed for selection. And the goal of the method is to make a check to return True/False.

💡Returning False is not necessary, since by default it will be None.
🪲Debugging
💡Important note:
If you have mistakes in your ISelectionFilter class, it will return False without any errors.
So if your filter doesn't work as expected and you can't select anything, you might have a typo or an error because it returns False to everything.
Some people spend hours trying to figure out why it's not working because they don't see any error messages. So go back and double check your code if you can't select anything.
Improve your Filter
Now, let's add even more logic to your filter.
We will keep the filter by category, but I also want to add a filter to ensure that elements are part of the group using elem.GroupId property.
This way it will become a really useful tool because of Revit limitation when selecting grouped elements. This way you will be able to easily drag and select elements of selected category inside groups.
Here is an updated MyFilter class with 2 if-statements.
And here is how it looks in action:
💡 Finally you can select grouped elements without smashing Tab button hundred times…
Bonus: Reuse your Classes
You can also create a reusable class with ISelectionFilter.
I will create 2 classes that can take arguments.
First one will take list of allowed Types, so we can specify what types of elements we want to allow selecting
Second one will take a list of allowed BuiltInCategories, with the same logic.
Maybe this will make it simpler for you to use.
To use these classes, we simply create instances of these classes.
Notice that we have create __init__ method, where we specified an argument allowed_type/allowed_categories. So make sure you provide the right types of elements in the list.
Add to lib
Now you can put these classes to your lib of reusable snippets and import when you need them. This way you only need to create a filter with simpler syntax and provide it as an argument.
I am sure you will find a lot of use-cases for these classes.
💡 Make sure you add them to you lib folder so you can import these classes.
e.g. lib/Snippets/_selection.py
Bonus: Advanced Example
Want more advanced example?
This snippet will only allow Walls with a height between 1 and 2 meters, and there should be a keyword 'Beton' in the TypeName.
P.S.
We will cover parameters in another module in more depth, for now this is just an example for you to see how to check multiple criterias.
💡 Bug in Revit 2022 or earlier
BuiltInCategory property is not accessible before Revit 2023.
So, it might not work if you try to use it in older versions.
As a workaround we can compare ElementIds of element's Category and our desired BuiltInCategory. It will have the same effect in the end.
Here is the simplified Snippet
🤐 Sorry for not mentioning this during the video.
ISelectionFilter might look confusing until you start using it yourself.
So I'd recommend to spend 5-15 minutes practicing.
Copy my example
Adjust to another category and test it
Maybe even try an Advanced example i provided
And while you are practicing I want you to write it from scratch at least once.
Because if you'll copy-paste all examples and not write much yourself, you won't remember it next time. So write it from scratch at least once.
⌨️ Happy Coding!
This is an older lesson that cover the same lesson materials. It might be useful if you'd like to understand this lesson better and see a bit different examples.
P.S.
I'll also show you how to create reusable class to place in your lib in this video.
⌨️ Happy Coding!