I've tried below code.
class ScheduleCommand : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
Document doc = commandData.Application.ActiveUIDocument.Document;
FamilyInstance assemblyInstance = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).WhereElementIsNotElementType().Cast<FamilyInstance>().FirstOrDefault(x => x.Symbol.FamilyName.Equals("Sample Window Family"));
if (assemblyInstance is FamilyInstance)
{
Dictionary<string, int> nestedFamilies = GetNestedFamilyNamesAndCounts(doc, assemblyInstance);
string resultMsg = "The Family '" + assemblyInstance.Name + "' containsthe following families:\n";
foreach (var item in nestedFamilies)
{
resultMsg += $"- {item.Key}: {item.Value} instance(s)\n";
}
TaskDialog.Show("Nested Family Details", resultMsg);
}
return Result.Succeeded;
}
private Dictionary<string, int> GetNestedFamilyNamesAndCounts(Document doc, FamilyInstance assemblyInstance)
{
Dictionary<string, int> nestedFamilyCounts = new Dictionary<string, int>();
ICollection<ElementId> nestedComponentIds = assemblyInstance.GetSubComponentIds();
foreach (var nestedComponentId in nestedComponentIds)
{
FamilyInstance familyInstance = doc.GetElement(nestedComponentId) as FamilyInstance;
if (familyInstance != null)
{
string nestedFamilyName = familyInstance.Symbol.Name;
if (nestedFamilyCounts.ContainsKey(nestedFamilyName))
{
nestedFamilyCounts[nestedFamilyName]++;
}
else
{
nestedFamilyCounts[nestedFamilyName] = 1;
}
}
}
return nestedFamilyCounts;
}
}
It didn't work as the below line of code returned null.
ICollection<ElementId> nestedComponentIds = assemblyInstance.GetSubComponentIds();
Also I've tried this code as well:
Document doc = commandData.Application.ActiveUIDocument.Document;
FilteredElementCollector familyCollector = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance));
foreach (FamilyInstance familyInstance in familyCollector)
{
if (familyInstance.Symbol.FamilyName == "Sample Window Family")
{
Dictionary<string, int> nestedFamilies = GetVisibleNestedFamilyNamesAndCounts(doc, familyInstance);
string resultMessage = "The family '" + familyInstance.Name + "' contains the following visible nested families:\n";
foreach (var family in nestedFamilies)
{
resultMessage += $"- {family.Key}: {family.Value} instance(s)\n";
}
TaskDialog.Show("Visible Nested Family Count", resultMessage);
}
}
private Dictionary<string, int> GetVisibleNestedFamilyNamesAndCounts(Document doc, FamilyInstance parentFamilyInstance)
{
Dictionary<string, int> nestedFamilyCounts = new Dictionary<string, int>();
FilteredElementCollector collector = new FilteredElementCollector(doc)
.OfClass(typeof(FamilyInstance));
foreach (FamilyInstance instance in collector)
{if (instance.Host != null && instance.Host.Id == parentFamilyInstance.Id)
{
if (IsFamilyInstanceVisible(instance))
{
string nestedFamilyName = instance.Symbol.FamilyName;
if (nestedFamilyCounts.ContainsKey(nestedFamilyName))
{
nestedFamilyCounts[nestedFamilyName]++;
}
else
{
nestedFamilyCounts[nestedFamilyName] = 1;
}
}
}
}
return nestedFamilyCounts;
}
private bool IsFamilyInstanceVisible(FamilyInstance instance)
{
Parameter visibilityParam = instance.get_Parameter(BuiltInParameter.IS_VISIBLE_PARAM);
if (visibilityParam != null && visibilityParam.AsInteger() == 0)
{
return false;
}
return true;
}
This approach didn't work as the collector didn't collect the nested familyInstances actually.
I'd appreciate any potential suggestions that will help to achieve the goal.