0

I'm having a problem with the method uidoc.PostRequestForElementTypePlacement(). It seems that the method is always requesting to use the architectural placement instead of the structural one. Is there any way to call the structural wall/floor placement?

Or is it possible to wait for the user to place with the method en then set the parameter "Structural" to true afterwards? I'm not sure how to do this as the above method does not get executed immediately but instead when the user brings focus back to the Revit view.

Thanks in advance.

Edit, added minimal code:

using System;
using System.Collections.Generic;
using System.Linq;

using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;

namespace Test2
{
    [TransactionAttribute(TransactionMode.Manual)]
    [RegenerationAttribute(RegenerationOption.Manual)]
    public class Test2 : IExternalCommand
    {
        List<ElementId> addedElementIds = new List<ElementId>();
        UIApplication _uiapp;

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

            addedElementIds.Clear();

            WallType wallType = new FilteredElementCollector(doc).OfClass(typeof(WallType)).Cast<WallType>().Last();

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

            uiDoc.PostRequestForElementTypePlacement(wallType);

            return Result.Succeeded;
        }

        void OnDocumentChanged(object sender, DocumentChangedEventArgs e)
        {
            addedElementIds.AddRange(e.GetAddedElementIds());

            Autodesk.Revit.ApplicationServices.Application app = _uiapp.Application;
            Document doc = _uiapp.ActiveUIDocument.Document;

            foreach (ElementId id in addedElementIds)
            {
                Element el = doc.GetElement(id);

                el.LookupParameter("Structural").Set(1);
            }

            app.DocumentChanged -= new EventHandler<DocumentChangedEventArgs>(OnDocumentChanged);
        }
    }
}
Jan Buijs
  • 98
  • 1
  • 6

2 Answers2

0

You could use the same approach to retrieve newly created instances using the DocumentChanged event as described to Place a Family Instance using PromptForFamilyInstancePlacement.

Jeremy Tammik
  • 7,333
  • 2
  • 12
  • 17
  • Hey Jeremy, thanks for answering, but this method is not reliable enough. I added the code of my test addin to my original question. It does work sometimes but not with all walls that you place. Also, when using a FloorType instead of WallType, it never works. – Jan Buijs Apr 17 '18 at 13:49
  • Would there be any other way to get around this @jeremy? – Jan Buijs Apr 18 '18 at 06:17
  • @JanBuijs you may need to subscribe to the `DocumentChanged` event *before* launching your external command, not inside its `Execute` method. – Jeremy Tammik Apr 18 '18 at 14:34
0

PostRequestForElementTypePlacement is described as delaying the actual request for placement of the family until "outside of the API". This (based on my experimentation) in a family whose parameters cannot be changed by the same program that placed it, and seems to ignore the event handler ".DocumentChanged" (since the document does not change until after the API is complete). Note that there is a bug in R2018 (verified by RevitAPIDocs, still there through 2018.3) which prevents "PromptForFamilyInstancePlacement" from being used, since "Esc" is returning a COMPLETE CANCEL to the API -- so there's no way to exit the placement tool without deleting the newly placed element. So your answer (per Jeremy's answer) is to use "PromptForFamilyInstancePlacement" on pre-2018 code.

(edit) OR BETTER YET, place the "PromptForFamilyInstancePlacement" inside a "try", with a "Catch Exception" -- apparently, this will catch the bogus exception created by the modification of the API. This is based on a posting by Jeremy Tamik on another site.

  • Except that there is no way to place a wall or floor with PromptForFamilyInstancePlacement, so that's not really an option. Thanks for the insight though. Looks like I'll have to find a workaround some other way. – Jan Buijs May 01 '18 at 04:48
  • Seems that the only way that I currently know of to let the user create a structural wall is to just place it somewhere through the API, set parameter "Structural" to 1, then let Revit select it and activate the command "Create Similar". I found a post by Jeremy to do this by using keyboard shortcuts. I'm still hoping there is some better way to do it though. – Jan Buijs May 01 '18 at 04:57
  • I have added options to my programs to "Update existing", and change the parameters on the element added via "PostRequestForElementTypePlacement" after creating the element (Selection.PickObject(s)). This of course seems excessive -- it would be better to change parameter values immediately after placing the element. – KeachyPeenReturns May 02 '18 at 21:57