One element can have several elements and components. For example, FamilyInstance has SubComponents and Wall has CompoundStructure which contain several CompoundStructureLayers. (For more details about SubComponents refer to the Family Instances section and refer to Walls, Floors, Roofs and Openings for more information about CompoundStructure.)
In the Revit Platform API, get an element's materials using the following guidelines:
If the Element object has a Parameter where ParameterType is ParameterType.Material, you can get the element material from the Parameter. For example, a structural column FamilySymbol (a FamilyInstance whose Category is BuiltInCategory.OST_StructuralColumns) has the Structural Material parameter. Get the Material using the ElementId. The following code example illustrates how to get the structural column Material that has one component.
Code Region: Getting an element material from a parameter |
public void GetMaterial(Document document, FamilyInstance familyInstance) { foreach (Parameter parameter in familyInstance.Parameters) { Definition definition = parameter.Definition; // material is stored as element id if (parameter.StorageType == StorageType.ElementId) { if (definition.ParameterGroup == BuiltInParameterGroup.PG_MATERIALS && definition.ParameterType == ParameterType.Material) { Autodesk.Revit.DB.Material material = null; Autodesk.Revit.DB.ElementId materialId = parameter.AsElementId(); if (-1 == materialId.IntegerValue) { //Invalid ElementId, assume the material is "By Category" if (null != familyInstance.Category) { material = familyInstance.Category.Material; } } else { material = document.GetElement(materialId) as Material; } TaskDialog.Show("Revit","Element material: " + material.Name); break; } } } } |
Some material properties contained in other compound parameters are not accessible from the API. As an example, in the following figure, for System Family: Railing, the Rail Structure parameter's StorageType is StorageType.None. As a result, you cannot get material information in this situation.
Figure 107: Rail structure property
Beam, Column and Foundation FamilyInstances have another way to get their material using their StructuralMaterialId property. This property returns an ElementId which identifies the material that defines the instance's structural analysis properties.
Code Region: Getting an element material from a family instance |
public Material GetFamilyInstanceMaterial(Document document, FamilyInstance beam) { Material material = document.GetElement(beam.StructuralMaterialId) as Material; return material; } |
Only model elements can have material.
From the Revit Manage tab, click SettingsObject Styles to display the Object Styles dialog box. Elements whose category is listed in the Model Objects tab have material information.
Figure 108: Category material
Only Model elements can have the Material property assigned. Querying Material for a category that corresponds to other than Model elements (e.g. Annotations or Imported) will therefore always result in a null. For more details about the Element and Category classifications, refer to Elements Essentials.
If an element has more than one component, some of the Category.Subcategories correspond to the components.
In the previous Object Styles dialog box, the Windows Category and the Frame/Mullion and Glass subcategories are mapped to components in the windows element. In the following picture, it seems the window symbol Glass Pane Material parameter is the only way to get the window pane material. However, the value is By Category and the corresponding Parameter returns ElementId.InvalidElementId.
In this case, the pane's Material is not null and it depends on the Category OST_WindowsFrameMullionProjection's Material property which is a subcategory of the window's category, OST_Windows. If it returns null as well, the pane's Material is determined by the parent category OST_Windows. For more details, refer to Walkthrough: Get Materials of a Window.
Figure 109: Window material
You can get the CompoundStructureLayer object from HostObjAttributes. For more details, refer to Walls, Floors, Ceilings, Roofs and Openings.
The following diagram shows the workflow to retrieve Element Materials:
Figure 110: Getting Element Material workflow
This workflow illustrates the following process:
The following code illustrates how to get the Window Materials.
Code Region: Getting window materials walkthrough |
public void GetMaterial(Document document, FamilyInstance window) { Materials materials = document.Settings.Materials; FamilySymbol windowSymbol = window.Symbol; Category category = windowSymbol.Category; Autodesk.Revit.DB.Material frameExteriorMaterial = null; Autodesk.Revit.DB.Material frameInteriorMaterial = null; Autodesk.Revit.DB.Material sashMaterial = null; // Check the paramters first foreach (Parameter parameter in windowSymbol.Parameters) { switch (parameter.Definition.Name) { case "Frame Exterior Material": frameExteriorMaterial = materials.get_Item(parameter.AsElementId()); break; case "Frame Interior Material": frameInteriorMaterial = materials.get_Item(parameter.AsElementId()); break; case "Sash": sashMaterial = materials.get_Item(parameter.AsElementId()); break; default: break; } } // Try category if the material is set by category if (null == frameExteriorMaterial) frameExteriorMaterial = category.Material; if (null == frameInteriorMaterial) frameInteriorMaterial = category.Material; if (null == sashMaterial) sashMaterial = category.Material; // Show the result because the category may have a null Material, // the Material objects need to be checked. string materialsInfo = "Frame Exterior Material: " + (null != frameExteriorMaterial ? frameExteriorMaterial.Name : "null") + "\n"; materialsInfo += "Frame Interior Material: " + (null != frameInteriorMaterial ? frameInteriorMaterial.Name : "null") + "\n"; materialsInfo += "Sash: " + (null != sashMaterial ? sashMaterial.Name : "null") + "\n"; TaskDialog.Show("Revit",materialsInfo); } |