Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Modify class with ISelectionFilter interface

8 REPLIES 8
SOLVED
Reply
Message 1 of 9
EATREVITPOOPCAD
1141 Views, 8 Replies

Modify class with ISelectionFilter interface

    public class addPickFilter : ISelectionFilter
    {
        public bool AllowElement(Element e)
        {
			return (e.Category.Id.IntegerValue.Equals((int)BuiltInCategory.OST_Rooms));
        }

        public bool AllowReference(Reference r, XYZ p)
        {
            return false;
        }
    }

Is there a way to change this class after creating it? I am trying to create a dynamic element selection filter that changes allowed elements to be selected based on user input.  So if the user selects one option it would allow him to select only rooms, or he can choose to be able to select only walls, or he can choose to be able to select rooms and walls. 

 

The only way I can think of doing this is by creating a class with ISelectionFilter interface for every possible outcome....

 

Is there a better way? maybe I could pass an input variable to this class for filter types (=not sure how that works with the interface, because my assumption is that interface has inputs predefined) 

 

Or is there a way to do pass multiple filters to Selection.PickObjects() ?  Something like

IList<Reference> objects = sel.PickObjects(ObjectType.Element, roomPickFilter + wallPickFilter, "Select objects");

 

 

The definition of insanity is doing the same thing over and over again and expecting different results
8 REPLIES 8
Message 2 of 9
AGGilliam
in reply to: EATREVITPOOPCAD

You can't pass multiple filters into the PickObjects method, but you can create a class similar to LogicalOrFilter to combine multiple filters into one. That's what I do, then just create the individual selection filters and combine them when necessary within the external command.
Message 3 of 9

Thank you will try it! 

The definition of insanity is doing the same thing over and over again and expecting different results
Message 4 of 9
jshial
in reply to: EATREVITPOOPCAD

how about declaring a list of category as property? something like (pseudo code):

 

 

 

 

 

public class addPickFilter : ISelectionFilter
    {
        private List<BuiltInCategory> _categoryMask;
        public List<BuiltInCategory> CategoryMask {get {return this._categoryMask}; 
        set {
             // set a list of categories with value keyword, check null ...
         };}
        
        ctor (List<BuiltInCategory> b_cats){
           // Initialize CategoryMask
        }


public bool AllowElement(Element e)
        {
			// loop through the mask
                         foreach (BuiltInCategory cat in mask)
                         {
                             if (match) return true;  
                         }

                         return  false
;        }

        public bool AllowReference(Reference r, XYZ p)
        {
            return false;
        }
    }

 

 

 

 

Message 5 of 9

@jshial Thank you for the example! I get the concept but everything falls apart at execution 😅 I will come back to solving this scenario your way when my c# is stronger and have more free time...

 

Here is how I went about this... I found a premade SelFilter class, you can read more about it here: https://thebuildingcoder.typepad.com/blog/2014/12/selfilter-a-powerful-generic-selection-filter-util...

 

SelFilter is a very nifty class, and I believe I kind of ghetto rigged it to do what I need it to do with the whole typeof(int)... In leu of type(int) I really wanted a null there but PickObjects() wouldn't initiate in Revit if one of the filters created with SelFilter.GetElementFilter() had null as its parameter

 

 

 

 

                ISelectionFilter userFilter = SelFilter.GetElementFilter( 
                    addAreas == true ? typeof(Wall) : typeof(int),              
                    addFloors == true ? typeof(Floor) : typeof(int),            
                    addRoofs == true ? typeof(RoofBase) : typeof(int),
                    addRooms == true ? typeof(Room) : typeof(int),
                    addWalls == true ? typeof(Wall) : typeof(int)
                    ); // Ideally 'type(int)' should be 'null' but 'null' doesnt work...

                IList<Reference> listOfObjects = sel.PickObjects(ObjectType.Element, userFilter , "Select objects:");

 

 

 

 

EDIT: ... void is what I was looking for! Now this baby is legit

                ISelectionFilter userFilter = SelFilter.GetElementFilter( 
                    addAreas == true ? typeof(Wall) : typeof(void),              
                    addFloors == true ? typeof(Floor) : typeof(void),            
                    addRoofs == true ? typeof(RoofBase) : typeof(void),
                    addRooms == true ? typeof(Room) : typeof(void),
                    addWalls == true ? typeof(Wall) : typeof(void)
                    );

                IList<Reference> listOfObjects = sel.PickObjects(ObjectType.Element, userFilter , "Select objects:");

 

 

 

 

The definition of insanity is doing the same thing over and over again and expecting different results
Message 6 of 9

Very minor hint: if your variable `addAreas` is a Boolean, then it has exactly two values: `true` and `false` The return value of comparing it with `true` is also a Boolean with the exact same identical two values. Hence, you can simply skip the `== true` part of the statement. Depending on your taste, that might improve readability. It definitely save a couple of bytes of code text, making it shorter. For me, personally, shorter equals easier to read. Just 2c worth...

  

Jeremy Tammik, Developer Advocacy and Support, The Building Coder, Autodesk Developer Network, ADN Open
Message 7 of 9

thanks @jeremy_tammik , i think removing the ==true is cleaner also

The definition of insanity is doing the same thing over and over again and expecting different results
Message 8 of 9
AGGilliam
in reply to: EATREVITPOOPCAD

Thanks for sharing your findings, this is a much nicer implementation than what I had in mind. Here's an example of one of the classes I use for selections (there are quite a few):

public class CornerTrimFilter : TBSFilter
    {
        public override bool AllowElement(Element e)
        {
            if (e is FamilyInstance)
            {
                FamilyInstance fi = e as FamilyInstance;
                if (fi.Symbol.FamilyName.Contains("CORNER TRIM"))
                    return true;
                if (fi.Symbol.FamilyName.Contains("STARTER TRIM"))
                    return true;
            }
            return false;
        }
    }

TBSFilter was just a generic class I used as a base class for setting parameters. I went with this method since the majority of our components are Generic Models, so we usually have nothing to compare except for family or type names.

Message 9 of 9

@AGGilliam I see, this makes more sense now... Thank you sir

The definition of insanity is doing the same thing over and over again and expecting different results

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Customer Advisory Groups


Rail Community