Category Comparison

Still giving Revit Structure API training in Verona, Italy, we ran into a problem in one of the Revit SDK samples today. The FrameBuilder sample works with structural beams and framing elements. It implements a FrameData class which defines an Initialize() method to set up internal lists of column, beam and brace symbols. These are sorted into different lists depending on their type, which is determined by comparing the category names. Unfortunately, the original SDK sample compares the category names with the language dependent strings "Structural Framing" and "Structural Columns". In the Italian version of Revit, these strings change to "Pilastri strutturali" and "Telaio strutturale" and the comparison will never succeed.

Here is the original, language dependent comparison code that we would like to replace by language independent code:

// add symbols to lists according to category name
string categoryName = symbol.Category.Name;
if ("Structural Framing" == categoryName)
{
  m_beambracesSymbolsMgr.AddSymbol(symbol);
}
else if ("Structural Columns" == categoryName)
{
  m_columnSymbolsMgr.AddSymbol(symbol);
}

To replace this by language independent code, we make use of the built-in category enumeration. We use the enumeration values OST_StructuralColumns and OST_StructuralFraming to obtain the corresponding document categories from the document settings and its categories collections, and store their element ids:

Document doc =
  m_commandData.Application.ActiveDocument;
 
Categories categories
  = doc.Settings.Categories;
 
BuiltInCategory bipColumn
  = BuiltInCategory.OST_StructuralColumns;
 
BuiltInCategory bipFraming
  = BuiltInCategory.OST_StructuralFraming;
 
ElementId idColumn
  = categories.get_Item( bipColumn ).Id;
 
ElementId idFraming
  = categories.get_Item( bipFraming ).Id;

This can be done right at the beginning of the Intialize() method. Then we can replace the language dependent code listed above by:

// add symbols to lists according to category
ElementId categoryId = symbol.Category.Id;
if( idFraming.Equals( categoryId ) )
{
  m_beambracesSymbolsMgr.AddSymbol( symbol );
}
else if( idColumn.Equals( categoryId ) )
{
  m_columnSymbolsMgr.AddSymbol( symbol );
}

Note that in previous versions of Revit, 2008 and earlier, it was possible to compare the categories directly, i.e. use something like this:

Category cat = symbol.Category;
if( catFraming.Equals( cat ) )
{
  m_beambracesSymbolsMgr.AddSymbol( symbol );
}
else if( catColumn.Equals( cat ) )
{
  m_columnSymbolsMgr.AddSymbol( symbol );
}

This stopped working reliably in Revit 2009, so nowadays you need to compare the category element ids instead of directly comparing the categories.