DocumentChanged versus PostRequestForElementTypePlacement

DocumentChanged versus PostRequestForElementTypePlacement

ari.monteiro
Advocate Advocate
1,890 Views
5 Replies
Message 1 of 6

DocumentChanged versus PostRequestForElementTypePlacement

ari.monteiro
Advocate
Advocate

Hello everyone!

 

I wrote an ExternalCommand that inserts components using the PostRequestForElementTypePlacement () method and I would like to get a list of the last components inserted.

 

Searching in the API documentation I checked that the method in question does not return the control to the API after the command is canceled by the user. Only the PromptForFamilyInstancePlacement () method runs within the context of the API, but it does not solve my problem because I need to adjust the insert options before inserting the component into the project.

 

The PromptForFamilyInstancePlacement () method has an overload where it allows you to use an object of class PromptForFamilyInstancePlacementOptions but, unfortunately, this class has no member that allows us to adjust the insert options.

 

In summary, the PostRequestForElementTypePlacement () method is the most appropriate method for my application and is only missing a way to get a list of the last components inserted.

 

I thought about implementing the DocumentChanged event as shown in the code below, but it is not working. See the comments bellow in red. What can you suggest me in this case?

 

I also saw in the documentation a method called PostCommand (). This method allows, if I understood correctly, to call a command from Revit and after the command is terminated by the user to return the process control to the application. Can I use this method together with PostRequestForElementTypePlacement () in some way to solve my problem?

 

    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class DharmaCmdInserirComponente : IExternalCommand
    {
        List<ElementId> _added_element_ids = new List<ElementId>();

        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Autodesk.Revit.ApplicationServices.Application app = uiapp.Application;
            Document doc = uidoc.Document;

            FilteredElementCollector collector
              = new FilteredElementCollector(doc);

            collector.OfCategory(BuiltInCategory.OST_Doors);
            collector.OfClass(typeof(FamilySymbol));

            FamilySymbol symbol = collector.FirstElement() as FamilySymbol;

            _added_element_ids.Clear();

            app.DocumentChanged += new EventHandler<DocumentChangedEventArgs>(myDocumentChanged);

            //IN THIS POINT THE API PASSES THE CONTROL TO THE REVIT FOR THE USER INSERT THE COMPONENTS
            //BUT WHEN THE USER PRESSES ESC TWICE, THE CONTROL DOES NOT RETURN TO APPLICATION
            uidoc.PostRequestForElementTypePlacement(symbol);

            //IN PRACTICE, THIS CODE IS EXECUTED. BUT BEFORE THE METHOD PostRequestForElementTypePlacement
            app.DocumentChanged -= new EventHandler<DocumentChangedEventArgs>(myDocumentChanged); 

            int n = _added_element_ids.Count;

           //Contagem dos últimos components inseridos 
TaskDialog.Show( "Número de componentes inseridos",
string.Format( "{0} components {1} adicionados.", n, ((1 == n) ? "" : "s"))); return Result.Succeeded; } void myDocumentChanged(object sender, DocumentChangedEventArgs e)
{ added_element_ids.AddRange(e.GetAddedElementIds()); } }

 

0 Likes
Accepted solutions (1)
1,891 Views
5 Replies
Replies (5)
Message 2 of 6

matthew_taylor
Advisor
Advisor
Hi,
After reading this, and taking note of the 'post' prefix to the routine name, it's apparent that this is how it's supposed to work:
http://www.revitapidocs.com/2017/f9bf4ed3-0354-6bc1-6db3-e34fcbace950.htm

After that, you have several options:
-use promptfor.... instead
-use promptfor... with a dummy family, and delete the instances, and replace with your new ones, perhaps with a new host or such
-use an iupdater to handle your families after placement
-use some sort of server to manipulate your families upon placement. This one is just a guess...I have no experience here.
I also wonder if your suggestion about post command would work. Disadvantages: A single transaction may be undone, leaving the families in limbo.

I hope my thoughts stimulate your thought processes.
Maybe you could tell us exactly what you are trying to do?

Cheers,

-Matt

Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
0 Likes
Message 3 of 6

ari.monteiro
Advocate
Advocate

Hi, Matt!

 

Thanks for your fast return!

 

Let me explain better what I want do. I need to get the last components inserted by PostRequestForElementTypePlacement ( ) method. Then I want to fill some parameters in these components.

 

My strategy was implement the DocumentChanged event to get the ElementIds of last components inserted and then fill some parameters.

 

But, as I explained on previous menssage, when the PostRequestForElementTypePlacement ( ) method is executed, the DocumentChanged event doesn't work. This event seems does not triggered when this method is running.

 

So, I'm looking for suggestions to use PostRequestForElementTypePlacement ( ) method and DocumentChanged event together in this context.

0 Likes
Message 4 of 6

matthew_taylor
Advisor
Advisor
Accepted solution

Hi Ari,

No problem.

 

To use the DocumentChanged event with PostRequestForElementTypePlacement, you would need to have the event working outside the context of your external command (i.e. an application level event). While this would work, it would take 'overhead' - use up system resources - and wouldn't be transparent to the user with regards to undoing and redoing transactions. (You would need to do have the event working outside the context of your command because the PostRequestForElementTypePlacement function doesn't actually start until your command returns control to Revit - read the page on the link I provided for further details.)

 

An iUpdater is *definitely* the way to go. They sound scary, but are actually quite simple (especially if you're only worried about created elements - as opposed to modified). An iUpdater uses the open transaction to 'slip' modifications in.

Jeremy Tammik has a blog post with sample code that may guide you: http://thebuildingcoder.typepad.com/blog/2010/08/structural-dynamic-model-update-sample.html

There are also examples in the SDK.

 

Let me know if you have any further questions.

 

Cheers,

 

-Matt


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
Message 5 of 6

ari.monteiro
Advocate
Advocate

Thanks, Matt!

 

The IUpdater implementation had works fine for me. Good suggestion!

 

Regards,

Ari

0 Likes
Message 6 of 6

matthew_taylor
Advisor
Advisor

Hi Ari,

Excellent news! Glad it worked for you.

 

Cheers,

 

-Matt


Cheers,

-Matt
_______________________________________________________________________________
Marking a post as a 'solution' helps the community. Giving a post 'Kudos' is as good as saying thanks. Why not do both?
0 Likes