Element Material

Element Material

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:

Material in a Parameter

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;
            }
        }
    }
}
Note: If the material property is set to By Category in the UI, the ElementId for the material is ElementId.InvalidElementId and cannot be used to retrieve the Material object as shown in the sample code. Try retrieving the Material from Category as described in the next section.

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

Material and FamilyInstance

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;
}

Material and Category

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

CompoundStructureLayer Material

You can get the CompoundStructureLayer object from HostObjAttributes. For more details, refer to Walls, Floors, Ceilings, Roofs and Openings.

Retrieve Element Materials

The following diagram shows the workflow to retrieve Element Materials:

Figure 110: Getting Element Material workflow

This workflow illustrates the following process:

  • The workflow shows how to get the Material object (not Autodesk.Revit.DB.Structure.StructuralMaterialType enumerated type) that belongs to the element.
  • There are two element classifications when retrieving the Material:
    • HostObject with CompoundStructure - Get the Material object from the CompoundStructureLayer class MaterialId property.
    • Others - Get the Material from the Parameters.
  • When you get a null Material object or an invalid ElementId with a value of ElementId.InvalidElementId, try the Material from the corresponding category. Note that a FamilyInstance and its FamilySymbol usually have the same category.
  • The more you know about the Element object, the easier it is to get the material. For example:
    • If you know the Element is a beam, you can get the instance parameter Structural Material
    • If you know the element is a window, you can cast it to a FamilyInstance and get the FamilySymbol.
  • After that you can get the Parameters such as Frame Exterior Material or Frame Interior Material to get the Material object. If you get null try to get the Material object from the FamilySymbol Category.
  • Not all Element Materials are available in the API.

Walkthrough: Get Window Materials

The following code illustrates how to get the Window Materials.

Code Region: Getting window materials walkthrough

public void GetMaterial(Document document, FamilyInstance window)
{
    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 parameters first
    foreach (Parameter parameter in windowSymbol.Parameters)
    {
        switch (parameter.Definition.Name)
        {
            case "Frame Exterior Material":
                frameExteriorMaterial = document.GetElement(parameter.AsElementId()) as Material;
                break;
            case "Frame Interior Material":
                frameInteriorMaterial = document.GetElement(parameter.AsElementId()) as Material;
                break;
            case "Sash":
                sashMaterial = document.GetElement(parameter.AsElementId()) as Material;
                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);
}