IUpdater. Get family instance and update values

IUpdater. Get family instance and update values

Anonymous
Not applicable
2,866 Views
5 Replies
Message 1 of 6

IUpdater. Get family instance and update values

Anonymous
Not applicable

Hey All,

 

My goal: Update a families parameter values from the api when shape handles are pulled. 

What works: Iupdater class that fires off my custom code when a user manipulates the shape handles on a family

What Doesnt work: updating the parameters of the family.

 

I have an IUpdater class that is fired only when family instances are changed. See snippet:

 

UpdaterRegistry.RegisterUpdater(MyFamilyInstance_updaterClass);
ElementClassFilter familyInstancesFilter = new ElementClassFilter(typeof(FamilyInstance));
UpdaterRegistry.AddTrigger(avt_FamilyInstance_updater.GetUpdaterId(), familyInstancesFilter, Element.GetChangeTypeGeometry());

Here is what I have tried and am experiencing a problem with: (this is located in the execute method of the updater class)

 

 

ICollection<ElementId> modifiedCollection = data.GetModifiedElementIds(); 
foreach (ElementId elemId in modifiedCollection) { Element elem = doc.GetElement(elemId); FamilyInstance fi = elem as FamilyInstance; if (fi != null) { FamilySymbol fsb = doc.GetElement(fi.GetTypeId()) as FamilySymbol; if (fsb != null) {
Parameter param = fi.GetParameters("calculated_Depth_of_Box").FirstOrDefault(); param.SetValueString("4");
} }
}

My problem is that it doesnt seem to update the parameter, and it loops infinitely (until revit crashes it) My guess is the reasoning is because im not filtering the modified collection enough. My end goal here is to get the family thats shape handle has been pulled, loop through each of its parameters (or find them, as I have the names stored in a list), and then set a value. (in this example just setting "4" but I have more advanced match being applied that is currently disabled while I figure this out)

 

Where am I going wrong in my approach here?

 

Thanks in advance for any help you all can give!

 

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

jeremytammik
Autodesk
Autodesk

When you say 'Revit is looping', it might be that the modification you apply in the updater Execute method triggers the same updater again, starting an infinite loop.

 

There are different levels of triggers and updaters. You may want to modify those so that the changes you make do not re-trigger your updater.

 

Alternatively, you might be able to add a switch to your updater Execute so that it is only active once, and deactivated when it gets called a second time in the same transaction, to step out of the infinite loop.

 

Maybe some of these other DMU samples will help resolve the problem:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.31

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 6

Anonymous
Not applicable

Apologies for the late reply. Yes it does appear to be an infinite loop that gets canceled. I will look through some more examples.

 

Im not quite sure what you mean by activating and deactivating using a switch or re triggering.  Obviously, I somehow need to limit this to prevent the infinite loop from happening. It does not seem (at least to me) overly obvious on how to get the family reference/parameters in the family being updated.

0 Likes
Message 4 of 6

FAIR59
Advisor
Advisor

To prevent the loop, I usually test to see if the new value differs from the oldvalue.

 

string newValue = "4";
if (param.AsValueString()!= newValue)  param.SetValueString(newValue);
0 Likes
Message 5 of 6

Anonymous
Not applicable
Accepted solution

Many thanks for your reply. Adding switch works. I think you are right the updater was triggering itself. 

I write my example for the others to use as a sample. 

 

 

namespace MyRevitCommands

{

    public class SampleUpdaterApplication : IExternalApplication

    {

        public Result OnShutdown(UIControlledApplication application)

        {

            SampleUpdater updater = new SampleUpdater(application.ActiveAddInId);

            UpdaterRegistry.UnregisterUpdater(updater.GetUpdaterId());

            return Result.Succeeded;

        }

 

        public Result OnStartup(UIControlledApplication application)

        {

            // Register updater with Revit

            SampleUpdater updater = new SampleUpdater(application.ActiveAddInId);

            UpdaterRegistry.RegisterUpdater(updater);

 

            // Change Scope = any element

 

            ElementClassFilter EleFilter1 = new ElementClassFilter(typeof(FamilyInstance));

 

            // Change type = element addition

            UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), EleFilter1, Element.GetChangeTypeAny());

            return Result.Succeeded;

 

        }

    }

   

 

    public class SampleUpdater : IUpdater

    {

        static AddInId m_appId;

        static UpdaterId m_updaterId;

 

        // constructor takes the AddInId for the add-in associated with this updater

        public SampleUpdater(AddInId id)

        {

            m_appId = id;

            m_updaterId = new UpdaterId(m_appId, new Guid("AF36588E-3E7A-48AB-85B4-52D0F2063DBE"));

        }

        public int caseswitch = 1;

 

 

        public void Execute(UpdaterData data)

        {

           

            switch (caseswitch)

            {

                case 1:

                Document doc = data.GetDocument();

                ICollection<ElementId> EleIdsModified = data.GetModifiedElementIds();

 

                foreach (ElementId eleid in EleIdsModified)

                {

                    Element ele = doc.GetElement(eleid);                  

                   

                        

                            //Write your code here

 

                 

                    }

                      

                }

                caseswitch = 2;

                break;

 

                case 2:

                TaskDialog.Show("case 2", "SampleUpdater");

                caseswitch = 1;

                break;

            }

           

        }

       

 

        public string GetAdditionalInformation()

        {

            return "SampleUpdater: Will update all of the required parameters of project";

        }

 

        public ChangePriority GetChangePriority()

        {

            return ChangePriority.MEPFixtures;

        }

 

        public UpdaterId GetUpdaterId()

        {

            return m_updaterId;

        }

 

        public string GetUpdaterName()

        {

            return "Updater";

        }

    }

}

@jeremytammik Thanks for your help. That was perfect!

0 Likes
Message 6 of 6

Anonymous
Not applicable

Thank you all for the replies! The switch also seems to be working well, and I added a check to ensure the value is different from the previous one.

0 Likes