Thursday, November 25, 2010

A Classy Way to Handle Revit Parameters

You may have noticed some of my previous posts referencing a clsPara object. I've been getting lots of interesting questions regarding this object and how it's built and just what the heck it does. Well... I guess I'll share.

My clsPara class is entirely reusable and very handy for handling data transactions in and out of parameters. Not only does this object connect with built-in parameters, it also connects with element properties! I know, its SO super exciting (breathe).

Let's start from the beginning... create a new class named clsPara and add the basic Autodesk.Revit reference as illustrated below.


Imports Autodesk.Revit

''' <summary>
''' An awesome class used to define a parameter
''' </summary>
''' <remarks></remarks>
Public Class clsPara

End Class

The next thing we need to do is provide a constructor that we can use to build this class into a meaningful object. All we need to accept as an argument is a Revit parameter. We'll handle all the rest internally within the class in a very simple yet highly efficient manner.


Private m_parameter As DB.Parameter

''' <summary>
''' Constructor
''' </summary>
''' <param name="parameter">Revit Parameter Object</param>
''' <remarks></remarks>
Public Sub New(ByVal parameter As DB.Parameter)
   m_parameter = parameter
End Sub

Our new clsPara object can now be called from anywhere in the project with the following code and argument (where myParam is a valid Revit Parameter reference):


Dim myLittleParam As New clsPara(myParam)

The next step is to provide all the basic data interaction routines and properties. We'll start with the data interactions for retrieving data from a Revit Parameter within the class.


''' <summary>
    ''' Get a parameter's value
    ''' </summary>
    ''' <param name="parameter"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetParameterValue(ByVal parameter As DB.Parameter) As String
        'public static Object GetParameterValue(Parameter parameter) 
        Select Case parameter.StorageType
            Case DB.StorageType.[Double]
                'get value with unit, AsDouble() can get value without unit 
                Return parameter.AsDouble
            Case DB.StorageType.ElementId
                ' Returns Only the ElementID
                Return parameter.AsElementId.IntegerValue
            Case DB.StorageType.[Integer]
                'get value with unit, AsInteger() can get value without unit 
                Return parameter.AsInteger
            Case DB.StorageType.None
                Return parameter.AsValueString()
            Case DB.StorageType.[String]
                Return parameter.AsString()
            Case Else
                Return ""
        End Select
    End Function

Now another function to SET a value to a parameter:


''' <summary>
    ''' Set a Parameter's value
    ''' </summary>
    ''' <param name="parameter"></param>
    ''' <param name="value"></param>
    ''' <remarks></remarks>
    Public Shared Sub SetParameterValue(ByVal parameter As DB.Parameter, ByVal value As Object)
        'first,check whether this parameter is read only 
        If parameter.IsReadOnly Then
            Exit Sub
        End If
        Select Case parameter.StorageType
            Case DB.StorageType.[Double]
                'set value with unit, Set() can set value without unit 
                parameter.SetValueString(TryCast(value, String))
                Exit Select
            Case DB.StorageType.ElementId
                Dim myElementId As DB.ElementId = DirectCast((value), DB.ElementId)
                parameter.[Set](myElementId)
                'MsgBox("Reminder to finish elementid write routine...")
                Exit Select
            Case DB.StorageType.[Integer]
                'set value with unit, Set() can set value without unit 
                parameter.SetValueString(TryCast(value, String))
                Exit Select
            Case DB.StorageType.None
                parameter.SetValueString(TryCast(value, String))
                Exit Select
            Case DB.StorageType.[String]
                parameter.[Set](TryCast(value, String))
                Exit Select
            Case Else
                Exit Select
        End Select
    End Sub

Now that we can set and get a value for a Revit Parameter... let's add some functionality to react within the class using some handy properties!!! Exciting, I know....


''' <summary>
    ''' This property will return the value!!
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Property Value() As String
        Get
            Try
                Return GetParameterValue(m_parameter)
            Catch
                Return Nothing
            End Try
        End Get
        Set(ByVal value As String)
            Try
                SetParameterValue(m_parameter, value)
            Catch
            End Try
        End Set
    End Property

    ''' <summary>
    ''' What's the unit type, anyway?
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property DisplayUnitType() As String
        Get
            Try
                Return m_parameter.DisplayUnitType.ToString
            Catch
                Return Nothing
            End Try
        End Get
    End Property

    ''' <summary>
    ''' True if this is a Read Only parameter such as Area!!
    ''' Will not fail when trying to write to a read-only parameter!!
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ParameterIsReadOnly() As Boolean
        Get
            Try
                Return m_parameter.IsReadOnly
            Catch
                Return Nothing
            End Try
        End Get
    End Property

    ''' <summary>
    ''' Returns true or false if this is a Shared Parameter!
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ParameterIsShared() As Boolean
        Get
            Try
                Return m_parameter.IsShared
            Catch
                Return Nothing
            End Try
        End Get
    End Property

    ''' <summary>
    ''' Returns the type of parameter, sometimes useful
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ParaType() As String
        Get
            Try
                Return m_parameter.GetType.Name
            Catch
                Return Nothing
            End Try
        End Get
    End Property

    ''' <summary>
    ''' Returns the parameter name
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property ParaName() As String
        Get
            Try
                Return m_parameter.Definition.Name
            Catch
                Return Nothing
            End Try
        End Get
    End Property

    ''' <summary>
    ''' This property will return the data format!
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public ReadOnly Property Format() As String
        Get
            Try
                Return m_parameter.StorageType.ToString
            Catch
                Return Nothing
            End Try
        End Get
    End Property

... I know!!! Don't forget to breathe!!