I was hoping someone more knowledgable than I could explain what I am seeing with the 2 code snippets below. The first grabs a colletion of Family type objects with a collector, while the second grabs a collection of FamilyInstance type objects.
Questions:
Code Snippet 1
ElementClassFilter FamilyFilter = new ElementClassFilter(typeof(Family));
FilteredElementCollector FamilyCollector = new FilteredElementCollector(RvtDoc);
ICollection<Element> AllFamilies = FamilyCollector.WherePasses(FamilyFilter).ToElements();
foreach (Family Fmly in AllFamilies)
{
string FamilyName = Fmly.Name;
foreach (Parameter Param in Fmly.Parameters)
{
string ParamName = Param.Definition.Name;
}
}
Code Snippet 2
ElementClassFilter FamilyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
FilteredElementCollector FamilyInstanceCollector = new FilteredElementCollector(RvtDoc);
ICollection<Element> AllFamilyInstances = FamilyInstanceCollector.WherePasses(FamilyInstanceFilter).ToElements();
foreach (FamilyInstance FmlyInst in AllFamilyInstances)
{
string FamilyInstanceName = FmlyInst.Name;
foreach (Parameter Param in FmlyInst.Parameters)
{
string ParamName = Param.Definition.Name;
}
}
The ultimate goal was to build a list of all parameters under each family in the Revit Document, but the differences I've encountered between Family objects and FamilyInstance objects has me fairly confused as to just how all of this works!
Thanks for any insight you can provide!
Solved! Go to Solution.
Solved by DJB_CADfx. Go to Solution.
The Revit API is working just as you have observed. The idea is that you can have either family parameters, type parameters or instance parameters. Those can be accessed (directly) only trough corresponding API object (Family, Type or FamilyInstance).
If you want to access for example type parameters trough instance, you have to use FamilyInstance.Symbol property to get the type element, which in turns has access to those parameters.
I would also recomend to get familiarise your self with the lookup/snooby add-in whick can be found from SDK. From there you can observe the same that I explained above.
Thanks for your input.
I'm mainly interested in the Shared Parameters. So if I want to collect all shared parameters on families in a revit document, am I correct in thinking that it is necessary to look at the parameters found on both the Family type elements and FamilyInstance type elements in the document. Then check all of those paramerers to find all that have IsShared set to true?
Actually, there would be a problem with this because it would get parameters from all Family objects. I only want the ones that have an instance in the document. Therefore, I'm guessing I need to do only the FamilyInstance search and from each FamilyInstance obtain its associated Family type to get its parameters as well.
However, I'm not seeing any way to go from the FamilyInstance object to its associated Family object. Is there a method in the API for doing this?
That's the way it goes IMO.
And there is a way to get the whole chain: FamilyInstance -> FamilySymbol (type) -> Family
From FamilyInstance object it is "Symbol" property. That gives you FamilySymbol object.
Furthermore from FamilySymbol you can get "Family" property which gives you Family object.
So there are these three levels which can contain shared parameters. Hope this helps.
Many thanks Ollikat, I think I get it now! Let me summarize my understanding for any future viewers of this post. If I have anything incorrectly stated, please let me know:
Code Snippet
ElementClassFilter FamilyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));
FilteredElementCollector FamilyInstanceCollector = new FilteredElementCollector(RvtDoc);
ICollection<Element> AllFamilyInstances = FamilyInstanceCollector.WherePasses(FamilyInstanceFilter).ToElements();
List<string> ParamLst = new List<string>();
FamilySymbol FmlySmbl;
Family Fmly;
foreach (FamilyInstance FmlyInst in AllFamilyInstances)
{
FmlySmbl = FmlyInst.Symbol;
Fmly = FmlySmbl.Family;
// Add Instance Parameter names to list
foreach (Parameter Param in FmlyInst.Parameters)
{
ParamLst.Add = Param.Definition.Name;
}
// Add Type Parameter names to list
foreach (Parameter Param in FmlySmbl.Parameters)
{
ParamLst.Add = Param.Definition.Name;
}
// Add Family Type Parameter names to list
foreach (Parameter Param in Fmly.Parameters)
{
ParamLst.Add = Param.Definition.Name;
}
}
Just an update for people viewing this in 2019, you may have to change "ParamLst.Add = Param.Definition.Name;" to "ParamLst.Add(Param.Definition.Name);"
Only one observation: only the FamilyInstance and the FamilySymbol can have SharedParameters, and the Parameters that can be accessed through the Family object are not TypeParameters, because they can not vary between the different types, but they show up under Type Parameters in the UI because there is no way to access the Families parameters through the UI (only if you select the Family Object by its ID)
Hi, thanks for the explanation
Im having a problem based on this functioning and im wondering if theres any solution or workaround to it.
If i have the familyInstance, i can get the instance parameters defined for the family type (which is represented by the familySymbol) and the their value within the instance. But what if i just have a loaded family, with familytypes, but not a placed familyInstance? i just want to be able to get the definition of the instance parameter (to check that the familytype will create an instance that contains said parameter, regardless of the value). Seems like i cannot check the existence of those parameters without having a placed instance.