Issue
I would like to set (or check mark) a classification in a property set definition using AutoCAD Architecture .NET API. In the UI, you can do this on the right hand side of "Applied To" tab. How can I do this?
Solution
The definitions of classifications are stored under the named object dictionary called "AEC_CLASSIFICATION_SYSTEM_DEFS". You can access it through DictionaryClassificationDefinition class. In order to retrieve a targeted classification, you will need to go through the tree structure of a classification definition. "Recursively listing classification definitions" shows how to list the classification definitions. For example, while traversing, you can compare the name and get its Object ID.
Once you have the Object ID of a targeted classification, you can set it, using
propSetDef.ClassificationFilter.Add(idClassification)
The following command demonstrates how to set a classification called "Load Bearing" (which you can find in metric template) to a property set definition named "wall" that is applicable to wall objects.
Imports System
Imports System.Diagnostics
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.Aec.DatabaseServices
Imports Autodesk.Aec.ApplicationServices
Imports Autodesk.Aec.Arch.DatabaseServices
Imports Autodesk.Aec.Arch.ApplicationServices
Imports Autodesk.Aec.PropertyData
Imports Autodesk.Aec.PropertyData.DatabaseServices
Imports Application = Autodesk.AutoCAD.ApplicationServices.Application
' To resolve ObjectId ambiguities
Imports ObjectId = Autodesk.AutoCAD.DatabaseServices.ObjectId
Imports ObjectIdCollection = Autodesk.AutoCAD.DatabaseServices.ObjectIdCollection
Public Class ACANETPropertySetDefinition2
'' add (or check mark) a classification to the given property set definition.
'' here we assume you have a prop set def called "wall" that applicable to wall objects.
'' and you want to add a classification called "Load Bearing" (which you can find in metric template).
'' Minimum error checking.
''
<CommandMethod("ACANet", "AddClassificationToPropSetDef", CommandFlags.Modal)> _
Public Sub AddClassificationToPropSetDef()
'' some basic things first.
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
'' get the dictionary of the prop set def
Dim dictPropSetDef As DictionaryPropertySetDefinitions =
New DictionaryPropertySetDefinitions(db)
'' find a prop set def with the given name.
'' for simplicity, we are hard-coding the name here.
'' we assume there is a prop set def called "wall"
''
Dim id As ObjectId = dictPropSetDef.GetAt("wall")
'' open it for write
Try
Using tr As Transaction = db.TransactionManager.StartTransaction
Dim obj As Object = tr.GetObject(id, OpenMode.ForWrite, False, False)
Dim propSetDef As PropertySetDefinition = CType(obj, PropertySetDefinition)
'' find a classification called "Load Bearing"
id = FindClassification("Load Bearing")
'' add classification
propSetDef.ClassificationFilter.Add(id)
tr.Commit()
End Using
Catch ex As Exception
ed.WriteMessage("error in AddPropSetDefClaasification: " + ex.ToString + vbCrLf)
End Try
End Sub
'' given a name of a classification, searches in classification definitions,
'' and return it's object id.
''
Shared Function FindClassification(ByVal sName As String) As ObjectId
'' Some basic things here
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim db As Database = HostApplicationServices.WorkingDatabase
Dim idClass As ObjectId = ObjectId.Null
'' Start a Transaction
Dim tr As Transaction = db.TransactionManager.StartTransaction
Try
'' get the dictionary for the classification definition, and list of records in it
''
Dim dict As DictionaryClassificationDefinition =
New DictionaryClassificationDefinition(db)
Dim ids As ObjectIdCollection = dict.Records
Dim id As ObjectId
'' loop through each classification def
''
For Each id In ids
Dim obj As Object = tr.GetObject(id, OpenMode.ForRead, False, False)
Dim classCollDef As ClassificationDefinition = obj
'' as an example, check to see if class def is applicable to Mass or Wall.
''
If classCollDef.AppliesToFilter.Contains("AecDbMassElem") Or _
classCollDef.AppliesToFilter.Contains("AecDbWall") Then
'' Found a classification definition
'' that was applied to AecDbMassElem/AcDbWall.
'' Get the tree and find a classification with the given name.
Dim classTree As ClassificationTree = classCollDef.ClassificationTree
idClass = FindClassification(sName, tr, classTree)
If idClass.IsValid Then
Return idClass
End If
End If
Next
Catch ex As ApplicationException
tr.Abort()
System.Windows.Forms.MessageBox.Show(ex.Message)
Finally
tr.Dispose()
End Try
Return idClass
End Function
'' helper function to find a classification.
'' Given a top most node of a tree, traverse the tree, and return the id.
''
Shared Function FindClassification(
ByVal name As String,
ByRef tr As Transaction,
ByRef node As ClassificationTree) As ObjectId
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim id As ObjectId = ObjectId.Null
If node Is Nothing Then
Return id
End If
'' let's get the name of the top most node.
''
If Not (node.Id.IsNull) Then
Dim classi As Classification =
CType(tr.GetObject(node.Id, OpenMode.ForRead), Classification)
If classi.Name.Equals(name) Then '' we found it.
Return classi.ObjectId
End If
End If
'' visit childen.
''
If node.Children.Count > 0 Then
'' this is a intemidiate node, go through each branch.
Dim child As ClassificationTree
For Each child In node.Children
id = FindClassification(name, tr, child)
If id.IsValid Then
Return id
End If
Next
End If
Return id
End Function
End Class