We have talked about getting information of shared parameters, attaching a shared parameter to some category instances, and creating new shared parameters. In this article, let’s see how to erase shared parameters or whether it is possible to achieve the goal programmatically with some straightforward APIs.
From checking on some relevant API classes and methods, it seems this is very achievable and in many ways. Firstly, the Definitions class or its parent DefinitionsBase has an Erase(Definition item) method which seems to do the right job; the Document.ParameterBindings property (actually the BindingMap class) has an Erase(Definition item) method too; and better it has another very similar method, Remove(Definition item), which seems to do the same job.
Let’s look at them one by one. The DefinitionsBase.Erase(Definition item) goes the first: public static List<T> RawConvertSetToList<T>(IEnumerable set)
{
List<T> list = (from T p in set select p).ToList<T>();
return list;
} public static bool RawEraseSharedParameterDefinition(RvtApplication app, string name, string group, ParameterType type)
{
DefinitionFile defFile = app.OpenSharedParameterFile();
if (defFile != null)
{
DefinitionGroup dg = RawConvertSetToList<DefinitionGroup>(defFile.Groups).FirstOrDefault(g => g.Name == group);
if (dg != null)
{
Definition def = RawConvertSetToList<Definition>(dg.Definitions).FirstOrDefault(d => d.Name == name);
if (def != null && def.ParameterType == type)
{
dg.Definitions.Erase(def);
return true;
}
}
} return false;
} Use the following test code to exercise it: … RawEraseSharedParameterDefinition(CachedApp, "Volume41", "Group4", ParameterType.Volume);
… However, out of most people’s expections, I believe, the following exception occurs:
Autodesk.Revit.Exceptions.InvalidOperationException: Collection is read-only
at Autodesk.Revit.DB.DefinitionsBase.Erase(Definition item) Q: How come?
A: No idea!
So the first most natural way does not work at all!
Let’s try the second approach: public static bool RawEraseSharedParameterBinding1(RvtApplication app, string name, ParameterType type)
{
BindingMap map = (new UIApplication(app)).ActiveUIDocument.Document.ParameterBindings;
DefinitionBindingMapIterator it = map.ForwardIterator();
it.Reset(); Definition def = null;
while (it.MoveNext())
{
if (it.Key != null && it.Key.Name == name && type == it.Key.ParameterType)
{
def = it.Key;
break;
}
} if (def != null)
{
map.Erase(def);
} return false;
} Use the following test code to exercise it: … RawEraseSharedParameterBinding1(CachedApp, "Volume41",ParameterType.Volume);
… However another exception occurs: Autodesk.Revit.Exceptions.InvalidOperationException at Autodesk.Revit.DB.BindingMap.Erase(Definition key)
Explanation: “The method Erase inherited from base class is not permitted for this class.”
Ok, now we have the last candidate left, the BindingMap.Remove(Definition key). public static bool RawEraseSharedParameterBinding2(RvtApplication app, string name, ParameterType type)
{
BindingMap map = (new UIApplication(app)).ActiveUIDocument.Document.ParameterBindings;
DefinitionBindingMapIterator it = map.ForwardIterator();
it.Reset(); Definition def = null;
while (it.MoveNext())
{
if (it.Key != null && it.Key.Name == name && type == it.Key.ParameterType)
{
def = it.Key;
break;
}
} if (def != null)
{
map.Remove(def);
} return false;
}
…
RawEraseSharedParameterBinding2(CachedApp, "Volume41",ParameterType.Volume);
… No exception occurs this time, but readers may come up with some questions: 1. What does the method really do for us?
2. Why is the Definition from the DefinitionBinding always InternalDefiniton?
3. Will it also delete the shared parameter definition entry in the external DefinitionFile?
4. If the answer to the above is NO, how to do so programmatically? A1:
The method removes the parameter binding actually just as its name suggests. Or speak it another way, the purpose of the method is to remove a project parameter instead of a shared parameter. And it is model specific rather than application specific which can be seen from the place they come from. The ParameterBindings comes from a Revit Document but the DefinitionFile is associated with the Revit Application through its SharedParametersFilename property and can be retrieved directly through the OpenSharedParameterFile() method call. Still confused? Don’t worry. We will get it finally. Let’s try to explain a bit more and demonstrate with some concrete examples. If the shared parameter ‘Volume41’ is defined but not bound at all to any categories or not linked/converted to a project parameter, the above approach does nothing at all. If a non-shared and bound parameter (or call it ‘naked project parameter’ if we like) has the same name as the shared parameter of our real concern, the non-shared parameter will be mistakenly removed from the current model and from all related elements/categories, all existing data will be lost, and all affected schedules and tags will look different! That could be a disaster in the real design world. It also violates the safety rules that Revit tries to build up for us, removing shared parameters will not affect any existing data, elements, and models. If we delete shared parameters programmatically this way, it goes exactly onto the opposite way. To make it clearer, here is a screenshot which shows some project parameters (or call them bound parameters if we like):
The first and the last ones are defined from shared parameters in the same sample ExternalFile that we addressed before. The middle three are real (or naked) project parameters. If you’d like to play around these a bit further, please rename any of the middle three as ‘Volume41’ with or without removing the last one, give the code one more try, and see what will be going on. So the third approach is really to delete a Project Parameter or parameter DefinitionBinding rather than a shared parameter. Totally different things! The first approach is the right one but it does not work! A2: Not so sure. Maybe to tell us that bound shared parameters are the same as other project parameters now and do not behave as ‘shared parameters’ anymore. A3: No, not at all. A4: We will address it in another future post. Revit Addin Coder of RevitAddinWizardcan help address and clarify various parameter matters including built-in parameter, family parameter, shared parameter, project parameter and more.
|