Save a Set of Elements with SelectionFilterElement

Here’s another great question from a reader! Is it possible to save a selection, with a name, and call upon it later?

Yes, it is.

public void SelectionFilter()
{
    Document doc = this.ActiveUIDocument.Document;
    UIDocument uidoc = new UIDocument(doc);

    // Prompt user to pick one or more elements
    IList<Reference> refList = uidoc.Selection.PickObjects(ObjectType.Element, "Pick elements to add to selection filter");

    // Create a transaction
    using (Transaction t = new Transaction(doc,"Create & Add To Selection Filter"))
    {
        t.Start(); // Start the transaction

        // Create a SelectionFilterElement
        SelectionFilterElement selFilter = SelectionFilterElement.Create(doc,"My Selection Filter");

        foreach (Reference r in refList) // Iterate through list of selected elements
        {
            // Add the ElementId of each selected element to the selection filter
            selFilter.AddSingle(r.ElementId);
        }

        // Commit the transaction
        t.Commit();
    }
}

After the filter is created it can be seen in the Filters dialog. It cannot be applied to a view but it can be used in other ways which is a a good topic for a future posts.

filterDialog

P.S. If you try to run this macro twice, it will fail the 2nd time because the filter names must be unique. The IsNameUnique method could be used to check for this case.

6 thoughts on “Save a Set of Elements with SelectionFilterElement

  1. I think I am going to be the code police for this one 🙂
    I totally understand and agree with that snippets published here are not intended to be (and should not be) up to production level. Typically, a lot of validations and error handling would have to be added, which is not at all necessity to show in the snippets presented herein. However, with just this particular code around object picking, I think it should be mentioned that if the end-user escapes the picking mode (by ether hitting the Esc key or the cancel button in Revit), the Revit API will throw an exception as a way of notifying the API programmer. For that reason the OperationCancelledException should probably be always handled in code that invokes picking.

    And while I am on the subject, the transaction would typically not be started (or even instantiated) until after the picking is completed, mainly for the reason I have just mentioned above. (Naturally, the creation of the selection filter would have to be postponed too.)

    • Hi Policeman Lobel,

      Isn’t it enough that I am using the ugly “transaction using block” code that you suggested 🙂
      Seriously, you are right that the selection does not belong in the transaction, so I have moved it accordingly. But I disagree that I should include code to handle the OperationCancelledException every time I show an example with PickObject or PickObjects. I will write a separate post on the subject and hope that suffices.

  2. The transaction in this sample is fine the way it is, at least for demonstration purposes. The “using” block ensures the transaction will be rolled black and closed in case of an exception. I too do agree with you that you should not bother with exception handling in the code snippets you provide in this blog. (By the way, the snippets are great! A seriously good job!) However, the OperationCancelledException deserves an exception from that rule, in my opinion. It is so because escaping the picking mode is so very likely that handling of that particular exception should always be part of object picking operation. I do not think you need to change the snippet though; I just thought it should be noted at least as a comment.
    Cheers.

  3. I have a filters question:

    So I am trying to use a list of input strings to isolate them in a view using Revit API. I got this far, but I am getting stuck where I am trying to create a set that takes all elements in a view and removes ones that are created from input IDs. I am doing this to end up with a set of all elements except ones that i want to isolate.

    view = IN0 #active 3d view
    str_ids = IN1 #input list that contains a list of IDs as string values
    doc = __doc__
    collector = FilteredElementCollector(doc, view.Id)

    for i in str_ids:
    int_id = int(i)
    id = ElementId(int_id)
    element = doc.GetElement(id)
    element_set = ElementSet()
    element_set.Insert(element)

    elements_to_hide = collector.WhereElementIsNotElementType().Excluding(element_set).ToElements()

    #Assign your output to the OUT variable
    OUT = elements_to_hide

    I would greatly appreciate a help in solving this error. I am getting that “expected ICollection[ElementId], got set”. I am guessing the problem lies in a Excluding filter where i need to create a collection of Ids to exclude but I dont know how. Thank you in advance.
    I want to use the elements_to_hide later to hide them in a view so that I am left with the elements that I am inputting in as a string of ids.

    Thank you again!

  4. i was able to resolve the issue and a few more that you can probably see with this code. I didnt realize that IList and ICollections need to be imported seperately.
    from System.Collections.Generic import *
    This resolved my collections issue.

Leave a comment