Using GetChangeTypeElementAddition to trigger on new FamilyInstance
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
The end result I'm after is to propagate attached schema from Family (added to OwnerFamily at family editor stage) to the FamilyInstance when it first gets added to project. And I'm struggling to make it less trigger happy and more selective.
It's an adaptive family so I'm also trying to propagate it to ReferencePoints as well.
-using GetChangeTypeAny allows me to propagate to both;
-using GetChangeTypeGeometry allows me to propagate to FamilyInstance only;
-using GetChangeTypeElementAddition does nothing, it does get triggered when Family gets loaded into the project.
For filters I've tried:
LogicalOrFilter logicFilter = new LogicalOrFilter(
new ElementClassFilter(typeof(FamilyInstance)),
new ElementClassFilter(typeof(ReferencePoint))
);
LogicalOrFilter logicFilter = new LogicalOrFilter(
new ElementCategoryFilter(BuiltInCategory.OST_GenericModel),
new ElementCategoryFilter(BuiltInCategory.OST_AdaptivePoints)
);
Because of the remark on AddTrigger - "This method only works with CategoryFilter and ParameterFilter" which made no difference in this context.
I really want to avoid unnecessarily firing the IUpdater when I go to modify the FamilyInstance or its Adaptive Placement Points, and using GetChangeTypeElementAddition() is a logical choice, propagate the schema once and done, rather than have it get called upon any slight interaction or modification, but the way FamilyInstances get added to the project is bizarre to me, you'll only capture their ID's with GetModifiedElementIds() not GetAddedElementIds() same with ReferencePoints connected to the FamilyInstance.
Can the GetChangePriority be the culprit? I don't have a good grasp on it's purpose. But it didn't interfere when used with GetChangeTypeAny
public ChangePriority GetChangePriority() => ChangePriority.FreeStandingComponents;
Here's my Execute Implementation for the IUpdater:
public class MyElementAdditionUpdater : IUpdater
{
private readonly UpdaterId _updaterId;
public MyElementAdditionUpdater(AddInId addInId, Guid updaterGuid)
{
_updaterId = new UpdaterId(addInId, updaterGuid);
}
public void Execute(UpdaterData data)
{
Document doc = data.GetDocument();
Schema schema = Schema.Lookup(schemaGuid);
if (schema == null)
{
Debug.Print("Schema not found, exiting.");
return; // Exit if schema doesn't exist
}
ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
// Iterate over modified elements that are either FamilyInstance or ReferencePoint
foreach (ElementId modifiedElementId in data.GetModifiedElementIds())
{
Element modifiedElement = doc.GetElement(modifiedElementId);
if (!(modifiedElement is FamilyInstance || modifiedElement is ReferencePoint))
{
continue; // Skip if the element is neither FamilyInstance nor ReferencePoint
}
//GetDependentElements return FamilyInstance, from which Family schema could be copied
var dependentElementIds = modifiedElement.GetDependentElements(familyInstanceFilter);
foreach (ElementId dependentElementId in dependentElementIds)
{
FamilyInstance dependentFamilyInstance = doc.GetElement(dependentElementId) as FamilyInstance;
if (dependentFamilyInstance == null)
{
continue; // Skip if the dependent element is not a FamilyInstance
}
Family family = dependentFamilyInstance.Symbol.Family;
Entity familyEntity = family.GetEntity(schema);
if (familyEntity == null)
{
Debug.Print($"Schema not found in family: {family.Name}, skipping.");
continue; // Skip if the family does not have the schema
}
// Apply schema from family to both FamilyInstance and ReferencePoint
Entity instanceEntity = new Entity(schema);
bool schemaApplied = false;
foreach (Field field in schema.ListFields())
{
if (familyEntity.Schema == null)
{
continue; // Skip if the schema field does not exist in the family entity
}
string value = familyEntity.Get<string>(field); // Assuming field values are string for simplicity
instanceEntity.Set(field, value);
schemaApplied = true;
}
if (schemaApplied)
{
Debug.Print($"Preparing to apply schema to element ID: {modifiedElementId}, Type: {modifiedElement.GetType().Name}.");
try
{
modifiedElement.SetEntity(instanceEntity);
Debug.Print($"Schema applied from Family {family.Name} to element ID: {modifiedElementId}.");
}
catch (Exception ex)
{
Debug.Print($"Exception applying schema: {ex.Message}");
}
}
}
}
}
public string GetAdditionalInformation() => "Handles addition of new elements with a specific schema.";
public ChangePriority GetChangePriority() => ChangePriority.FreeStandingComponents;
public UpdaterId GetUpdaterId() => _updaterId;
public string GetUpdaterName() => "Custom Element Addition Updater";
}
The purpose of this attempt at propagation is so that I can have another IUpdater that will only get triggered in response to elements with schema that are getting manipulated by the user and to that end ExtensibleStorageFilter should do the job. But surely there's a better strategy to propagate Family Schema to it's FamilyInstance and other relevant objects.
Appreciate any help!