Hi. Is there any way to get the instance of the last placed family in the document?
If I use PrompForFamilyInstancePlacement(), I would like to get the family just inserted to manipulate the parameters. Thanks!
I haven't looked at this in detail, but I'm kinda surprised that the API doesn't provide the placed elements as the return value from this method. Actually, no I'm not.
I have one idea in mind that may work... You could create a class that 'captures' placed elements by handling the DocumentChanged event and then interrogate it after PromptForFamilyInstancePlacement() returns. Something like the following...
class ElementCatcher : IDisposable { Application application; bool disposed = false; public ElementCatcher(Application application) { this.application = application; this.AddedElementIds = new List<ElementId>(); application.DocumentChanged += new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged); } public void Dispose() { if (!disposed) { application.DocumentChanged -= new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged); disposed = true; } } void OnDocumentChanged(object sender, DocumentChangedEventArgs e) { AddedElementIds.AddRange(e.GetAddedElementIds()); } public List<ElementId> AddedElementIds { get; private set; } } class MyCommand : ICommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { using (var catcher = new ElementCatcher(commandData.Application.Application)) { var myFamilySymbol = // TODO: Get the FamilySymbol to be placed commandData.Application.ActiveUIDocument.PromptForFamilyInstancePlacement(myFamilySymbol); foreach (var id in catcher.AddedElementIds) { var addedElement = commandData.Application.ActiveUIDocument.Document.get_Element(id); // TODO: Process the added element } } return Result.Succeeded; } }
I would recommend checking the IUpdater Interface and example code provided within the API documentation. With this interface you can specify certaing triggers which cause the updater to act. For example one common way to use this is a creation of the new element.
sure, we can use the DocumentChanged event to retrieve the newly added family instances.
Another straightforward idea is to get the newly added family instance by ourself. Before call PromptForFamilyInstancePlacement(), using the FamilySymbolFilter to filter out all existiing family instance list that use the same FamilySymbol as PromptForFamilyInstancePlacement. Then after calling PromptForFamilyInstnacePlacement, using the same filter again to find a new list of family instances. Then compare the two lists to get the newly added family instances.
Question,
I cannot use OnDocumentChanged to change the parameter of an added family cause if I change the parameter, the OnDocumentChanged will be triggered again causing a loop and Revit is giving errors. How do you fix this problem? I tried removing the event inside the OnDocumentChanged function and the function did not continue executing... Thanks.
Thanks for the reply. I actually found a solution to this problem. I declared a global variable with type List and everytime the user add an entity in the drawing, the ondocumentchanged will only add this item to the List. After adding, the ondocumentchanged will finish executing and the program will return to the calling function and process the List. This way, we can modify the parameters of the added entities outside ondocumentchanged. 🙂
dear a7v1n,
i see that you discovered the use of subscribing temporarily to the DocumentChanged event to obtain the newly placed intance element ids one by one. congratulations! this is also described in detail in
http://thebuildingcoder.typepad.com/blog/2010/06/place-family-instance.html
best regards
jeremy
--
Jeremy Tammik
Autodesk Developer Network -- http://www.autodesk.com/joinadn
The Building Coder -- http://thebuildingcoder.typepad.com
Note that the ElementCatcher class I posted above provides this exact behavior in a simple re-usable class that wraps the event subscription / unsubscription and gathers the added element IDs without relying on global variables.
hey matt,
wow, yes, great post, thank you for that!
and thank you for poining it out again.
very sorry that i missed it in my first quick browse of this thread.
if you like, i can publish it on the blog as well to highlight it better.
cheers
jeremy