SetGroupTypeId for project parameters is not kept after closing the model

SetGroupTypeId for project parameters is not kept after closing the model

a.bejenaru
Enthusiast Enthusiast
888 Views
12 Replies
Message 1 of 13

SetGroupTypeId for project parameters is not kept after closing the model

a.bejenaru
Enthusiast
Enthusiast

I have created a macro which changes the group for some project parameters. The macro works and I see the prameters under the new groups. I save and close the model and when I open it again the parameters are under the original groups.

public void ModifyParameterGroup()
		{
			Document doc = this.ActiveUIDocument.Document;
			Autodesk.Revit.ApplicationServices.Application application = doc.Application;
			
			Dictionary<string, ForgeTypeId> paramDict = new Dictionary<string, ForgeTypeId>();

			//other
			paramDict.Add("R_TEST", GroupTypeId.Phasing);
			paramDict.Add("R_UniqueCatID", GroupTypeId.Phasing);

			BindingMap bindingsMap = doc.ParameterBindings;
			DefinitionBindingMapIterator iterator = bindingsMap.ForwardIterator();

			using (Transaction t = new Transaction(doc, "Change Parameter Group"))
			{
				t.Start();
				while (iterator.MoveNext())
				{
					ElementBinding elementBinding = iterator.Current as ElementBinding;
					Definition definition = iterator.Key;

					InternalDefinition intDef = definition as InternalDefinition;

					if (paramDict.ContainsKey(definition.Name))
						intDef.SetGroupTypeId(paramDict[definition.Name]);
				}
				t.Commit();
			}
		}
0 Likes
889 Views
12 Replies
Replies (12)
Message 2 of 13

ctm_mka
Collaborator
Collaborator

@a.bejenaru Please confirm if doing the same operations manually has the same result, or actually sticks upon re opening.

0 Likes
Message 3 of 13

a.bejenaru
Enthusiast
Enthusiast
yes, manually sticks in the new group after closing and opening.
0 Likes
Message 4 of 13

ricaun
Advisor
Advisor

Looks like a bug, I tested and was not able to save the new parameter group, really strange.

 

I tested in version 2024 - Build 24.0.4.427.

 

Here is a code with the file for testing. The file has a project parameter and a shared parameter.

public void ModifyParameterGroup(Document document)
{
    System.Console.WriteLine(document.Title);
    Dictionary<string, ForgeTypeId> paramDict = new Dictionary<string, ForgeTypeId>();

    //other
    paramDict.Add("R_TEST", GroupTypeId.Phasing);
    paramDict.Add("R_TEST_SHARED", GroupTypeId.Phasing);

    BindingMap bindingsMap = document.ParameterBindings;
    DefinitionBindingMapIterator iterator = bindingsMap.ForwardIterator();

    using (Transaction t = new Transaction(document))
    {
        t.Start("Change Parameter Group");
        while (iterator.MoveNext())
        {
            ElementBinding elementBinding = iterator.Current as ElementBinding;
            Definition definition = iterator.Key;

            InternalDefinition intDef = definition as InternalDefinition;
            if (paramDict.ContainsKey(definition.Name))
            {
                System.Console.WriteLine($"{definition.Name} \t {intDef.GetGroupTypeId().TypeId} -> {paramDict[definition.Name].TypeId}");
                intDef.SetGroupTypeId(paramDict[definition.Name]);
            }
        }
        t.Commit();
    }

    document.Save();
}

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 5 of 13

a.bejenaru
Enthusiast
Enthusiast

So I'm the first person to try this? I think this method is available since 2022

0 Likes
Message 6 of 13

ricaun
Advisor
Advisor

@a.bejenaru wrote:

So I'm the first person to try this? I think this method is available since 2022


Maybe yes.

I never needed to change the group in an existing document, maybe would be a good idea to check if that happened with the old BuiltInParameterGroup to see if works or not.

 

And... same issue, change the group is not saved, here is the code. (Tested in Revit 24.0.4.427.)

 

public void ModifyBuiltInParameterGroup(Document document)
{
    System.Console.WriteLine(document.Title);
    Dictionary<string, BuiltInParameterGroup> paramDict = new Dictionary<string, BuiltInParameterGroup>();

    //other
    paramDict.Add("R_TEST", BuiltInParameterGroup.PG_PHASING);
    paramDict.Add("R_TEST_SHARED", BuiltInParameterGroup.PG_PHASING);

    BindingMap bindingsMap = document.ParameterBindings;
    DefinitionBindingMapIterator iterator = bindingsMap.ForwardIterator();

    using (Transaction t = new Transaction(document))
    {
        t.Start("Change Parameter Group");
        while (iterator.MoveNext())
        {
            ElementBinding elementBinding = iterator.Current as ElementBinding;
            Definition definition = iterator.Key;

            InternalDefinition intDef = definition as InternalDefinition;
            if (paramDict.ContainsKey(definition.Name))
            {
                System.Console.WriteLine($"{definition.Name} \t {intDef.get_ParameterGroup()} -> {paramDict[definition.Name]}");
                intDef.set_ParameterGroup(paramDict[definition.Name]);
            }
        }
        t.Commit();
    }

    document.Save();
}

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 7 of 13

a.bejenaru
Enthusiast
Enthusiast

Is there another way of reaching a project parameter? Maybe the ElementBinding method fails.

0 Likes
Message 8 of 13

ricaun
Advisor
Advisor

I figure out the issue.

 

There is no transaction when you change the parameter group in the document, this means I can use SetGroupTypeId without a transaction. Probably the document never saves that change if you close and open the document again.

 

Here is a video. https://youtu.be/LMcxdK7WRx8

 

This is the Command in the video without transaction that changes the SetGroupTypeId.

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;

namespace RevitTestSample
{
    [Transaction(TransactionMode.Manual)]
    [System.ComponentModel.Designer("/UIFrameworkRes;component/ribbon/images/revit.ico")]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            UIApplication uiapp = commandData.Application;

            Document document = uiapp.ActiveUIDocument.Document;

            ModifyParameterGroup(document);

            return Result.Succeeded;
        }

        public void ModifyParameterGroup(Document document)
        {
            System.Console.WriteLine(document.Title);
            Dictionary<string, ForgeTypeId> paramDict = new Dictionary<string, ForgeTypeId>();

            //other
            paramDict.Add("R_TEST", GroupTypeId.Phasing);
            paramDict.Add("R_TEST_SHARED", GroupTypeId.Phasing);

            BindingMap bindingsMap = document.ParameterBindings;
            DefinitionBindingMapIterator iterator = bindingsMap.ForwardIterator();

            while (iterator.MoveNext())
            {
                ElementBinding elementBinding = iterator.Current as ElementBinding;
                Definition definition = iterator.Key;

                InternalDefinition intDef = definition as InternalDefinition;
                if (paramDict.ContainsKey(definition.Name))
                {
                    System.Console.WriteLine($"{definition.Name} \t {intDef.GetGroupTypeId().TypeId} -> {paramDict[definition.Name].TypeId}");
                    intDef.SetGroupTypeId(paramDict[definition.Name]);
                }
            }
        }
    }
}

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 9 of 13

a.bejenaru
Enthusiast
Enthusiast

So it is a bug?

0 Likes
Message 10 of 13

a.bejenaru
Enthusiast
Enthusiast

for now my solution is to run the code each time I open a document using the DocumentOpened Event

https://www.revitapidocs.com/2015/b9415c2d-442e-f61d-aafa-de31cce7959b.htm

Message 11 of 13

ricaun
Advisor
Advisor

@a.bejenaru wrote:

So it is a bug?


Yes, hey @jeremytammik, can you ask the Revit team to check that?

 

I tested in Revit 2021 and looks like changing the ParameterGroup in the project parameters never works. I can execute outside a Transaction and even outside the Revit context.

 

This command should fail without a transaction.

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;

namespace RevitTestSample
{
    [Transaction(TransactionMode.Manual)]
    public class Command : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            UIApplication uiapp = commandData.Application;

            Document document = uiapp.ActiveUIDocument.Document;

            ModifyBuiltInParameterGroup(document);

            return Result.Succeeded;
        }

        public void ModifyBuiltInParameterGroup(Document document)
        {
            System.Console.WriteLine(document.Title);
            Dictionary<string, BuiltInParameterGroup> paramDict = new Dictionary<string, BuiltInParameterGroup>();

            //other
            paramDict.Add("R_TEST", BuiltInParameterGroup.PG_PHASING);
            paramDict.Add("R_TEST_SHARED", BuiltInParameterGroup.PG_PHASING);

            foreach (var item in GetParameterBindings(document))
            {
                ElementBinding elementBinding = item.Value as ElementBinding;
                Definition definition = item.Key;

                InternalDefinition intDef = definition as InternalDefinition;
                if (paramDict.ContainsKey(definition.Name))
                {
                    System.Console.WriteLine($"{definition.Name} \t {intDef.get_ParameterGroup()} -> {paramDict[definition.Name]}");
                    intDef.set_ParameterGroup(paramDict[definition.Name]);
                }
            }
        }

        public IDictionary<Definition, Binding> GetParameterBindings(Document document)
        {
            var parameterBindings = document.ParameterBindings;
            var iterator = parameterBindings.ForwardIterator();
            var result = new Dictionary<Definition, Binding>();
            while (iterator.MoveNext())
            {
                var definition = iterator.Key as Definition;
                var binding = iterator.Current as Binding;
                result.Add(definition, binding);
            }
            return result;
        }

    }
}

 

I guess using the DocumentOpened Event kinda works momentarily.

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes
Message 12 of 13

studio-a-int
Advocate
Advocate

It is not a bug, you need to use ReInsert method exposed by Revit API, since the Shared Parameter exists in your Binding Map.

 

https://www.revitapidocs.com/2021.1/8ac26661-1c4b-6ba1-417f-e4ea09acf32c.htm


For older Revit versions use:
public virtual bool BindingMap.ReInsert(Definition key, Binding item, BuiltInParameterGroup parameterGroup)
For newer Revit versions use:
public virtual bool ReInsert(Definition key, Binding item, ForgeTypeId groupTypeId)

Use below method to change the Parameter Group for a Shared Parameter.
Synchronize, close the project, reopen it and the Parameter Group stays as set by this method.

public void ChangeParameterGroup(Autodesk.Revit.DB.Document activeDoc)
{
// Code provided courtesy of:
// Studio A International, LLC
// http://www.studio-a-int.com
// The code change the Parameter Group of selected Shared Parameter
// assume yourSharedParameter current Group is Identity Data
// through this method we assign it to IFC Group
// BuiltInParameterGroup.PG_IDENTITY_DATA -> GroupTypeId.IdentityData
// BuiltInParameterGroup.PG_IFC -> GroupTypeId.Ifc
BindingMap bindingsMap = activeDoc.ParameterBindings;
DefinitionBindingMapIterator iterator = bindingsMap.ForwardIterator();
using (Transaction t = new Transaction(activeDoc, "Change Parameter Group"))
{
t.Start();
while (iterator.MoveNext())
{
ElementBinding currentBinding = iterator.Current as ElementBinding;
Definition def = iterator.Key;
InternalDefinition intDef = def as InternalDefinition;
var initialDefParGroup = intDef.ParameterGroup.ToString();
if (def is object && def.Name == "yourSharedParameterName")
{
Autodesk.Revit.DB.Definition d;
d = def as Autodesk.Revit.DB.Definition;
string verBuild = activeDoc.Application.VersionBuild;
string verNumber = activeDoc.Application.VersionNumber;
/*
List<string> listVerNumbersOlder = new List<string> { "2020", "2021", "2022" };
if (verNumber is object && listVerNumbersOlder.Contains(verNumber))
{
activeDoc.ParameterBindings.ReInsert(d, currentBinding, BuiltInParameterGroup.PG_IFC);
}
*/
List<string> listVerNumbersNewer = new List<string> { "2023", "2024" };
if (verNumber is object && listVerNumbersNewer.Contains(verNumber))
{
activeDoc.ParameterBindings.ReInsert(d, currentBinding, GroupTypeId.Ifc);
}
System.Windows.Forms.MessageBox.Show("Parameter Group for : " +
"\r\n" + " " + def.Name +
"\r\n" + "was changed from: " +
"\r\n" + initialDefParGroup +
"\r\n" + "to: " +
"\r\n" + intDef.ParameterGroup.ToString() +
"\r\n" + "Revit Build Number: " +
"\r\n" + verBuild.ToString() +
"\r\n" + "Revit Version: " +
"\r\n" + verNumber.ToString(), "Parameter Group changed");
}
}
activeDoc.Regenerate();
t.Commit();
}
}

0 Likes
Message 13 of 13

ricaun
Advisor
Advisor

Yes, if you are using SharedParameter the ReInsert should work. But if you are using a ProjectParameter, the ReInsert does nothing.

 

The SetGroupTypeId/set_ParameterGroup still changes the propriety in the document but is not saved in a transaction.

 

 

using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System;
using System.Collections.Generic;

namespace RevitTestSample
{
    [Transaction(TransactionMode.Manual)]
    public class CommandReInsert : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet)
        {
            UIApplication uiapp = commandData.Application;

            Document document = uiapp.ActiveUIDocument.Document;

            // ModifyBuiltInParameterGroup(document);

            using (Transaction transaction = new Transaction(document))
            {
                transaction.Start("ReInsertBuiltInParameterGroup");
                ReInsertBuiltInParameterGroup(document); // Does not work with Project Parameter
                transaction.Commit();
            }

            return Result.Succeeded;
        }

        public void ModifyBuiltInParameterGroup(Document document)
        {
            System.Console.WriteLine(document.Title);
            Dictionary<string, BuiltInParameterGroup> paramDict = new Dictionary<string, BuiltInParameterGroup>();

            //other
            paramDict.Add("R_TEST", BuiltInParameterGroup.PG_PHASING);
            paramDict.Add("R_TEST_SHARED", BuiltInParameterGroup.PG_PHASING);

            foreach (var item in GetParameterBindings(document))
            {
                ElementBinding elementBinding = item.Value as ElementBinding;
                Definition definition = item.Key;

                InternalDefinition intDef = definition as InternalDefinition;
                if (paramDict.ContainsKey(definition.Name))
                {
                    System.Console.WriteLine($"{definition.Name} \t {intDef.get_ParameterGroup()} -> {paramDict[definition.Name]}");
                    intDef.set_ParameterGroup(paramDict[definition.Name]);
                }
            }
        }

        public void ReInsertBuiltInParameterGroup(Document document)
        {
            System.Console.WriteLine(document.Title);
            Dictionary<string, BuiltInParameterGroup> paramDict = new Dictionary<string, BuiltInParameterGroup>();

            //other
            paramDict.Add("R_TEST", BuiltInParameterGroup.PG_PHASING);
            paramDict.Add("R_TEST_SHARED", BuiltInParameterGroup.PG_PHASING);

            foreach (var item in GetParameterBindings(document))
            {
                Binding binding = item.Value;
                Definition definition = item.Key;

                InternalDefinition intDef = definition as InternalDefinition;
                if (paramDict.ContainsKey(definition.Name))
                {
                    System.Console.WriteLine($"{definition.Name} \t {intDef.get_ParameterGroup()} -> {paramDict[definition.Name]}");
                    //intDef.set_ParameterGroup(paramDict[definition.Name]);
                    //document.ParameterBindings.ReInsert(definition, binding);
                    document.ParameterBindings.ReInsert(definition, binding, paramDict[definition.Name]);
                }
            }
        }

        public IDictionary<Definition, Binding> GetParameterBindings(Document document)
        {
            var parameterBindings = document.ParameterBindings;
            var iterator = parameterBindings.ForwardIterator();
            var result = new Dictionary<Definition, Binding>();
            while (iterator.MoveNext())
            {
                var definition = iterator.Key as Definition;
                var binding = iterator.Current as Binding;
                result.Add(definition, binding);
            }
            return result;
        }

    }
}

 

 

 

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

0 Likes