In this section, we address adding per-document data, in contrast to the per-element data we have been discussing until now. In a nutshell, we suggest storing document data on an element as well, simply using a singleton element, i.e. one that appears only once per document.
Problem: We need a strategy to persistently store per-document or per-model data.
Solution: Bind (hidden or visible) shared parameters to the singleton element of 'Project Information' category.
We implement two commands to test this concept, to initialise and increment.
Add three name string variables to LabConstants class for later use, including one group name and two shared Parameter names
// Lab 4_4 public const string sParamGroupName = "Per-doc Params"; public const string sParamNameVisible = "Visible per-doc Integer"; public const string sParamNameInvisible = "Invisible per-doc Integer";
' Lab 4_4 Public Const sParamGroupName As String = "Per-doc Params" Public Const sParamNameVisible As String = "Visible per-doc Integer" Public Const sParamNameInvisible As String = "Invisible per-doc Integer"
First create a shared parameter group and two definitions of type Integer. All you need are three existing utilities from LabUtils:
#region Lab4_4_1_CreatePerDocParameters /// <summary> /// Command to add and bind a visible and an invisible per-doc parameter. /// </summary> public class Lab4_4_1_PerDocParams : IExternalCommand { public IExternalCommand.Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; // Get the current Shared Params Definition File DefinitionFile sharedParamsFile = LabUtils.GetSharedParamsFile( app ); if( null == sharedParamsFile ) { LabUtils.ErrorMsg( "Error getting the shared params file." ); return IExternalCommand.Result.Failed; } // Get or Create the Shared Params Group DefinitionGroup sharedParamsGroup = LabUtils.GetOrCreateSharedParamsGroup( sharedParamsFile, LabConstants.sParamGroupName ); if( null == sharedParamsGroup ) { LabUtils.ErrorMsg( "Error getting the shared params group." ); return IExternalCommand.Result.Failed; } //To do: Create the visible and invisible parameter definition //To do: Bind the parameter defition to element //to do: set value to per doc shared parameters return IExternalCommand.Result.Succeeded; } } #endregion // Lab4_4_1_CreatePerDocParameters
#Region "Lab4_4_1_CreatePerDocParameters" ''' <summary> ''' Command to add and bind a visible and an invisible per-doc parameter. ''' </summary> ''' <remarks></remarks> Public Class Lab4_4_1_PerDocParams Implements IExternalCommand Public Function Execute( _ ByVal commandData As ExternalCommandData, _ ByRef message As String, _ ByVal elements As ElementSet) _ As IExternalCommand.Result Implements IExternalCommand.Execute Implements Autodesk.Revit.IExternalCommand.Execute Dim app As Revit.Application = commandData.Application Dim doc As Revit.Document = app.ActiveDocument ' Get or create relevant shared params stuff: Dim sharedParamsFile As DefinitionFile = LabUtils.GetSharedParamsFile(app) If (sharedParamsFile Is Nothing) Then MsgBox("Error in getting the Shared Params File?") Return IExternalCommand.Result.Failed End If Dim sharedParamsGroup As Parameters.DefinitionGroup sharedParamsGroup = LabUtils.GetOrCreateSharedParamsGroup( _ sharedParamsFile, LabConstants.sParamGroupName) If (sharedParamsGroup Is Nothing) Then MsgBox("Error in getting the Shared Params Group?") Return IExternalCommand.Result.Failed End If 'To do: Create the visible and invisible parameter definition 'To do: Bind the parameter defition to element 'To do: set value to per doc shared parameters Return IExternalCommand.Result.Succeeded End Function End Class #End Region
When calling the last method, make one parameter visible and the other invisible.
// Visible param Definition docParamDefVisible = LabUtils.GetOrCreateSharedParamsDefinition( sharedParamsGroup, ParameterType.Integer, LabConstants.sParamNameVisible, true ); if( null == docParamDefVisible ) { LabUtils.ErrorMsg( "Error creating visible per-doc parameter." ); return IExternalCommand.Result.Failed; } // INVisible param Definition docParamDefInvisible = LabUtils.GetOrCreateSharedParamsDefinition( sharedParamsGroup, ParameterType.Integer, LabConstants.sParamNameInvisible, false ); if( null == docParamDefInvisible ) { LabUtils.ErrorMsg( "Error creating invisible per-doc parameter." ); return IExternalCommand.Result.Failed; }
' Visible param Dim docParamDefVisible As Parameters.Definition = LabUtils.GetOrCreateSharedParamsDefinition( _ sharedParamsGroup, ParameterType.Integer, LabConstants.sParamNameVisible, True) If (docParamDefVisible Is Nothing) Then MsgBox("Error in creating visible per-doc parameter?") Return IExternalCommand.Result.Failed End If 'INVisible param Dim docParamDefInvisible As Parameters.Definition = LabUtils.GetOrCreateSharedParamsDefinition( _ sharedParamsGroup, ParameterType.Integer, LabConstants.sParamNameInvisible, False) If (docParamDefInvisible Is Nothing) Then MsgBox("Error in creating invisible per-doc parameter?") Return IExternalCommand.Result.Failed End If
Bind these new parameters to the 'Project Information' category
BuiltInCategory.OST_ProjectInformation
in the current model
(cf. similar code in Lab 4.3.1).
// Bind the Param try { Document doc = app.ActiveDocument; CategorySet catSet = app.Create.NewCategorySet(); catSet.Insert( doc.Settings.Categories.get_Item( BuiltInCategory.OST_ProjectInformation ) ); Binding binding = app.Create.NewInstanceBinding( catSet ); doc.ParameterBindings.Insert( docParamDefVisible, binding ); doc.ParameterBindings.Insert( docParamDefInvisible, binding ); } catch( System.Exception e ) { LabUtils.ErrorMsg( "Error binding shared parameter: " + e.Message ); return IExternalCommand.Result.Failed; }
' Bind the params Try Dim catSet As CategorySet = app.Create.NewCategorySet() catSet.Insert(app.ActiveDocument.Settings.Categories.Item( _ BuiltInCategory.OST_ProjectInformation)) Dim binding As Parameters.Binding = app.Create.NewInstanceBinding(catSet) app.ActiveDocument.ParameterBindings.Insert(docParamDefVisible, binding) app.ActiveDocument.ParameterBindings.Insert(docParamDefInvisible, binding) Catch e As Exception MsgBox("Error in binding shared parameter: " & e.Message) Return IExternalCommand.Result.Failed End Try
Create a re-usable utility in LabUtils which will return the singleton element instance of 'Project Information' category.
/// <summary> /// Return the one and only project information element using Revit 2009 filtering /// by searching for the "Project Information" category. Only one such element exists. /// </summary> public static Element GetProjectInfoElem( Application app ) { Dim filterCategory As Revit.Filter = app.Create.Filter.NewCategoryFilter( _ BuiltInCategory.OST_ProjectInformation) ElementIterator i = app.ActiveDocument.get_Elements( filterCategory ); i.MoveNext(); Element e = i.Current as Element; Debug.Assert( null != e, "expected valid project information element" ); Debug.Assert( !i.MoveNext(), "expected one single element to be returned" ); return e; }
''' <summary> ''' Return the one and only project information element using Revit 2009 filtering ''' by searching for the "Project Information" category. Only one such element exists. ''' </summary> Public Shared Function GetProjectInfoElem( _ ByVal doc As Revit.Document, _ ByRef app As Revit.Application) As Revit.Element Dim filterCategory As Revit.Filter = app.Create.Filter.NewCategoryFilter( _ BuiltInCategory.OST_ProjectInformation) Dim elements As New List(Of Element) 'it should return only one element in the collection. Dim nRetVal As Integer nRetVal = doc.Elements(filterCategory, elements) ' Loop all elements Dim elem As Revit.Element For Each elem In elements ' Return the first match (it's a singleton!) If (Not (elem Is Nothing)) Then Return elem End If Next Return Nothing End Function
Use the above utility to retrieve the 'ProjectInfo' element, and set the value for the new shared parameter value.
// Set the initial values // Get the singleton Project Info Element Element projInfoElem = LabUtils.GetProjectInfoElem( app ); if( null == projInfoElem ) { LabUtils.ErrorMsg( "No project info elem found. Aborting command..." ); return IExternalCommand.Result.Failed; } // For simplicity, access params by name rather than by GUID: projInfoElem.get_Parameter( LabConstants.sParamNameVisible ).Set( 55 ); projInfoElem.get_Parameter( LabConstants.sParamNameInvisible ).Set( 0 );
' Set the initial values '----------------------- ' Get the singleton Project Info Element Dim projInfoElem As Revit.Element = LabUtils.GetProjectInfoElem(doc, app) If projInfoElem Is Nothing Then MsgBox("NO project Info Elem found !? Aborting command...") Return IExternalCommand.Result.Failed End If ' For simplicity, access params by name rather than by GUID: projInfoElem.Parameter(LabConstants.sParamNameVisible).Set(55) projInfoElem.Parameter(LabConstants.sParamNameInvisible).Set(0)
In this lab, we will increment the invisible parameter value by the following steps
#region Lab4_4_2_IncrementPerDocParameters /// <summary> /// Command to increment the invisible per-doc param /// </summary> public class Lab4_4_2_PerDocParams : IExternalCommand { public IExternalCommand.Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements ) { Application app = commandData.Application; // Get the singleton Project Info Element Element projInfoElem = LabUtils.GetProjectInfoElem( app ); if( null == projInfoElem ) { LabUtils.ErrorMsg( "No project info elem found. Aborting command..." ); return IExternalCommand.Result.Failed; } // For simplicity, access invisible param by name rather than by GUID: try { Parameter param = projInfoElem.get_Parameter( LabConstants.sParamNameInvisible ); // report OLD value int iOldValue = param.AsInteger(); LabUtils.ErrorMsg( "OLD value = " + iOldValue.ToString() ); // set and report NEW value param.Set( iOldValue + 1 ); LabUtils.ErrorMsg( "NEW value = " + param.AsInteger().ToString() ); } catch( System.Exception e ) { LabUtils.ErrorMsg( "Failed: " + e.Message ); return IExternalCommand.Result.Failed; } return IExternalCommand.Result.Succeeded; } } #endregion // Lab4_4_2_IncrementPerDocParameters
#Region "Lab4_4_2_IncrementPerDocParameters" ''' <summary> ''' Command to increment the invisible per-doc param ''' </summary> ''' <remarks></remarks> Public Class Lab4_4_2_PerDocParams Implements IExternalCommand Public Function Execute( _ ByVal commandData As ExternalCommandData, _ ByRef message As String, _ ByVal elements As ElementSet) _ As IExternalCommand.Result _ Implements IExternalCommand.Execute Dim app As Revit.Application = commandData.Application Dim doc As Revit.Document = app.ActiveDocument ' Get the singleton Project Info Element Dim projInfoElem As Revit.Element = LabUtils.GetProjectInfoElem(doc, app) If projInfoElem Is Nothing Then MsgBox("NO project Info Elem found !? Aborting command...") Return IExternalCommand.Result.Failed End If ' For simplicity, access invisible param by name rather than by GUID: Try Dim param As Parameter = projInfoElem.Parameter(LabConstants.sParamNameInvisible) ' report OLD value Dim iOldValue As Integer = param.AsInteger MsgBox("OLD value = " & iOldValue) ' set and report NEW value param.Set(iOldValue + 1) MsgBox("NEW value = " & param.AsInteger) Catch e As Exception MsgBox("Failed!? : " & e.Message) Return IExternalCommand.Result.Failed End Try Return IExternalCommand.Result.Succeeded End Function End Class #End Regionnext previous home copyright © 2007-2008 jeremy tammik, autodesk inc. all rights reserved.