Live link between Parameters in Model & Detail Families

Here’s the implementation of a suggestion from @BigBadBIM at RTCNA:

“Map a parameter value of a model component to an detail component that live updates when model changes. Idea was to link detail components used for elec riser diagrams at old firm.”

The user is prompted to select two elements – a model component and a detail component. The id of the detail component is stored in a parameter in the model component. The value of the parameter (“Fred”, for testing) is copied from the model component to the detail component.

Then an updater is created so that any time this parameter is changed in the model component, the value is automatically copied into the detail component.

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

    Element parent = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select model component"));
    Element detail = doc.GetElement(uidoc.Selection.PickObject(ObjectType.Element, "Select detail component"));

    string paramName = "Fred";
    Parameter detailParam = detail.get_Parameter(paramName);
    Parameter parentParam = parent.get_Parameter(paramName);

    using (Transaction t = new Transaction(doc,"Bind Param"))
      {
        t.Start();
        parent.get_Parameter("Child ID").Set(detail.Id.IntegerValue);
        detailParam.Set(parentParam.AsString());
        t.Commit();
    }

    ParameterUpdater updater = new ParameterUpdater(this.Application.ActiveAddInId);
    UpdaterRegistry.RegisterUpdater(updater);
    UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), new ElementClassFilter(typeof(FamilyInstance)), Element.GetChangeTypeParameter(parentParam.Id));
}

public class ParameterUpdater : IUpdater
{
    static AddInId m_appId;
    static UpdaterId m_updaterId;
    public ParameterUpdater(AddInId id)
    {
        m_appId = id;
        m_updaterId = new UpdaterId(m_appId, new Guid("F2FAF6B2-4C06-42d4-97C1-D1B4EB593EFF"));
    }
    public void Execute(UpdaterData data)
    {
        Document doc = data.GetDocument();
        Element parent = doc.GetElement(data.GetModifiedElementIds().First());
        if (parent.Category.Name == "Detail Items")
        	return;
        ElementId childID = new ElementId(parent.get_Parameter("Child ID").AsInteger());
        Element child = doc.GetElement(childID);
        string paramName = "Fred";
        child.get_Parameter(paramName).Set(parent.get_Parameter(paramName).AsString());
    }
    public string GetAdditionalInformation() { return "ParameterUpdater"; }
    public ChangePriority GetChangePriority() { return ChangePriority.FloorsRoofsStructuralWalls; }
    public UpdaterId GetUpdaterId() { return m_updaterId; }
    public string GetUpdaterName() { return "ParameterUpdater"; }
}

You can download an RVT to try this code at https://drive.google.com/file/d/0BwszsfY3OsZHZllJOEllWGl2aWs/edit?usp=sharing

10 thoughts on “Live link between Parameters in Model & Detail Families

  1. Could you please share family and u have used and the and and the way ur schedule u have presented it so that i can check, i tried may time but i dont t know weather the program rus or not bcoz when ever i paste the scrip i dosent run

    when i paste the program from line no.20 i.e from :-public class ParameterUpdater : IUpdater
    the program load successful
    but still i can’t find the way to run it properly
    i wann to use it to find XYZ cordinate for Adaptive points
    Please help

    • Here is the RVT
      https://drive.google.com/file/d/0BwszsfY3OsZHZllJOEllWGl2aWs/edit?usp=sharing

      Also I added these two lines to the code in the post. It may have been a change from 2013 to 2014 in the API that makes them necessary because I was seeing the updater triggered twice – once for when the parameter changes in the model component and then a 2nd time when the parameter changes in the detail component. We want the updater code to run only for the model component, so this check will cause the updater to exit when it is called for the detail component.
      if (parent.Category.Name == “Detail Items”)
      return;

  2. Harry,

    I’ve been struggling with getting this to work type parameters. Would you be able to show how it would work with a type parameter instead of an instance parameter?

      • Yes I have been able to access the family type parameters outside of the updater. It seems that the updater doesn’t trigger off of a change to a type parameter. . I was going to just put two parameters in, one a type parameter and an instance parameter. I figured I could set the instance parameter to be equal to type parameter. Apparently thought there is a quirk in Revit when you do this. If you set an instance parameter equal to a type parameter and then update the type parameter, the instance parameter doesn’t update. I decided to just use the updater with a trigger of any change. I would definitely prefer to use the parameter change but it doesn’t seem like it is works. If you have any insight it would be greatly appreciated.

        • >> If you set an instance parameter equal to a type parameter and then update the type parameter, the instance parameter doesn’t update

          Dynamic Model Update has protections that prevent infinite loops (updating one parameter updates a 2nd parameter, which updates the 1st parameter). You might look in the journal file for any evidence of this, or step through your code to see if an exception is thrown.

  3. I’m just learning this stuff (taking the Udemy course right now), so please forgive my ignorance (and impatience to make it to the end of the course…) if these are a elementary questions.

    1. I can get the above code to work for any text instance parameter by simply replacing Fred with another Parameter Name. But I cannot get it to work for a different type of instance parameter such as Force or Electrical Potential. Is there something else I am missing that I need to change to get that to work? Can it be done?

    2. If I wanted to have the above code work to update multiple parameters instead of just one, I assume that I could copy certain lines of the code and paste back into SharpDevelop and replace “paramName” with “paramName1”, “paramName2″……. Would this work and if so which lines would this need to happen for?

    Thanks-

    • Hi Ben,

      1) There is nothing special about the “Fred” parameter. What line of code causes the error when you try to use a different parameter? Note that the value “Fred” is hardcoded in two locations in this sample so you would need to change it in both places.

      2) To have this work with multiple “child” parameters you would need to replicate lines such as:
      detailParam.Set(parentParam.AsString());
      child.get_Parameter(paramName).Set(parent.get_Parameter(paramName).AsString());

  4. 1) The error I think was caused because I was trying to push the parent value (which was a Voltage parameter) to a Voltage parameter in the Child. I changed the Child Parameter to be a text parameter and changed the line to read:
    detailParam.Set(parentParam.AsValueString());

    It then worked to push the Voltage Parameter to text (again…I’m just learning this C# stuff)

    2) I wanted to get multiple parameters from the parent and update to multiple child parameters. Is it possible to have a single updater grab multiple parameters from the parent and update those parameters in the child? I have this:

    string paramName = “Panel Voltage”;
    string paramName1 = “Panel Name”;
    Parameter detailParam = detail.get_Parameter(paramName);
    Parameter parentParam = parent.get_Parameter(paramName);
    Parameter detailParam1 = detail.get_Parameter(paramName1);
    Parameter parentParam1 = parent.get_Parameter(paramName1);

    using (Transaction t = new Transaction(doc,”Bind Param”))
    {
    t.Start();
    parent.get_Parameter(“Child ID”).Set(detail.Id.IntegerValue);
    detailParam.Set(parentParam.AsValueString());
    detailParam1.Set(parentParam1.AsString());
    t.Commit();
    }

    and later:

    string paramName = “Panel Voltage”;
    string paramName1 = “Panel Name”;
    child.get_Parameter(paramName).Set(parent.get_Parameter(paramName).AsString());
    child.get_Parameter(paramName1).Set(parent.get_Parameter(paramName1).AsString());

    Is there something that also needs to be added/duplicated in terms of the “UpdaterRegistry.AddTrigger……” lines?

    Or did I just make a hot mess of the whole thing?

    I tried the Step Into and Revit crashed when it hit the Updater Registry lines..

    • Hi – If you are just getting started with the API, I’d suggest that you set aside the Updater functionality for now and come back to it after you’ve gotten the basic functionality working. Try to make a macro that gets and sets the desired parameter values. Once you have that working, then try to connect it to the updater.

Leave a comment