Issue accessing Materials of Railings via API

Issue accessing Materials of Railings via API

Anonymous
Not applicable
644 Views
3 Replies
Message 1 of 4

Issue accessing Materials of Railings via API

Anonymous
Not applicable

I recently built an add-in for Revit that selects elements by material. However a colleague brought to my attention that it does not seem to work for railings. Upon further investigation it seems that the getmaterialids method inherited from the Element class does not work for railings (at least not for me anyway ). I also couldn't seem to get the gethandrails method to return anything. Any help would be much appreciated.

0 Likes
645 Views
3 Replies
Replies (3)
Message 2 of 4

bhprest
Advocate
Advocate

For the intermediate rails (the ones defined in the revit UI under the Rail Structure panel), I don't think there's a way to access those through the API. If anyone knows better, I'd love to hear it.

 

For balusters and toprails: if you're working in 2019 or later, take a look at the Element.GetDependentElements() method. This will return a whole collection of elementIds that depend on the top-level railing element. This will include a lot of elements that you don't care about, so you'll have to filter for TopRails and FamilyInstances. The FamilyInstances will include your balusters.

 

For each instance that this returns, you'll then get the ElementType (use the Element.GetTypeId()). The types will have parameters on them which hold the material value. Balusters for example have a parameter on them named "Baluster Material". TopRails have a parameter called "Material". Other railing elements such as handrails may have others- you'll have to dig through to figure out which ones represent the materials you need to pull.

 

Good luck!

Message 3 of 4

bhprest
Advocate
Advocate

Followup to my previous post:

 

It does appear that you can get a list of all materials used on a railing by using the get_Geometry() method.

 

If you dig into the GeometryInstances that the method returns, then you can get a list of solids that represent the object geometry.  From the solids, you can iterate over Solid.Faces, and use the Face.MaterialElementId to get the material used on that face.

 

If you're just worried about IF the material is used, and not WHERE the material is used, then this appears to solve your issue.

 

 

Message 4 of 4

aysenakahraman98
Participant
Participant

// Get the active document from UI
Document doc = UIDoc.Document;

// Get the first open view's ID to work in the context of an active view
ElementId activeViewId = UIDoc.GetOpenUIViews()[0].ViewId;
View activeView = doc.GetElement(activeViewId) as View;

// Collect all Railing in the active view
List<Railing> railingsInView = new FilteredElementCollector(doc, activeViewId)
.OfClass(typeof(Railing))
.Cast<Railing>()
.ToList();

Logger.AppendLine($"Found {railingsInView.Count} railing(s) in the active view.");

foreach (Railing railing in railingsInView)
{
Logger.AppendLine($"\n--- Railing: {railing.Id.IntegerValue} ---");

// Get the dependent elements (e.g., balusters, top rails, handrails)
ICollection<ElementId> dependentElementIds = railing.GetDependentElements(null);

foreach (ElementId dependentId in dependentElementIds)
{
Element dependentElement = doc.GetElement(dependentId);

// --- TopRail ---
if (dependentElement is TopRail topRail)
{
TopRailType topRailType = doc.GetElement(topRail.GetTypeId()) as TopRailType;
if (topRailType != null)
{
Material material = GetMaterialFromParameters(doc, topRailType);
Logger.AppendLine($"Top Rail Material: {(material != null ? material.Name : "null")}");
}
}

// --- HandRail ---
else if (dependentElement is HandRail handRail)
{
HandRailType handRailType = doc.GetElement(handRail.GetTypeId()) as HandRailType;
if (handRailType != null)
{
Material material = GetMaterialFromParameters(doc, handRailType);
Logger.AppendLine($"Hand Rail Material: {(material != null ? material.Name : "null")}");
}
}

// --- Baluster (FamilyInstance) ---
else if (dependentElement is FamilyInstance baluster)
{
Material material = GetMaterialFromParameters(doc, baluster);
Logger.AppendLine($"Baluster Material: {(material != null ? material.Name : "null")}");
}
}
}

// Helper method to get material from parameters or category
Material GetMaterialFromParameters(Document doc, Element element)
{
foreach (Parameter param in element.Parameters)
{
Definition def = param.Definition;
if (param.StorageType == StorageType.ElementId &&
def.GetDataType() == SpecTypeId.Reference.Material)
{
ElementId materialId = param.AsElementId();
if (materialId != ElementId.InvalidElementId)
{
return doc.GetElement(materialId) as Material;
}
}
}

// Fallback: try getting from Category
return element.Category != null ? element.Category.Material : null;
}

0 Likes