Announcements
Attention for Customers without Multi-Factor Authentication or Single Sign-On - OTP Verification rolls out April 2025. Read all about it here.

Project Parameters not being created when a second document is opened

sensiblehira
Enthusiast

Project Parameters not being created when a second document is opened

sensiblehira
Enthusiast
Enthusiast
//Create project parameters
public static Guid CreateProjectParameter(Document doc, string parameterName,
    string groupName, ForgeTypeId parameterType, ForgeTypeId parameterGroup, bool instance,
    System.Collections.Generic.IEnumerable<Category> categoryList)
{
    // buffer the current shared parameter file name and apply a new empty parameter file instead
    string sharedParameterFile = doc.Application.SharedParametersFilename;
    string tempSharedParameterFile = System.IO.Path.GetTempFileName() + ".txt";
    using (System.IO.File.Create(tempSharedParameterFile)) { }
    doc.Application.SharedParametersFilename = tempSharedParameterFile;

    //check if the parameter exists
    bool parameterExists;
    Autodesk.Revit.DB.Binding existing_binding;
    Definition existing_definition;

    (parameterExists, existing_binding, existing_definition) = 
        CheckProjectParameter(doc, parameterName);

    // Get the BindingMap of the current document
    BindingMap bindingMap = doc.ParameterBindings;

    // Apply selected parameter categories
    CategorySet categories = new CategorySet();
    if (categoryList == null) //if true parameter is applied to all the categories in the document
    {
        foreach (Category c in doc.Settings.Categories)
        {
            if (parameterExists) 
            {
                if (CheckParameterExistsForCategory(doc, existing_definition, existing_binding, c))
                {
                    continue;//if the parameter exists for the category no changes are needed
                }
            }
            if (c.AllowsBoundParameters)
            {
                categories.Insert(c);
            }
        }
    }
    else
    {
        foreach (Category c in categoryList)
        {
            if (parameterExists)
            {
                if (CheckParameterExistsForCategory(doc, existing_definition, existing_binding, c))
                {
                    continue;
                }
            }
            if (c.AllowsBoundParameters)
            {
                categories.Insert(c);
            }
        }
    }
    if (categories.IsEmpty)
    {
        //if (existing_definition is ExternalDefinition existingExternalDefinition) return existingExternalDefinition.GUID;
        /*FilteredElementCollector collector = new FilteredElementCollector(doc).OfClass(typeof(ParameterElement));
        foreach (SharedParameterElement para in collector)
        {
            if (para.Id == (InternalDefinition)existing_definition.Id) return para.GuidValue;
        }*/
        InternalDefinition existingInternalDefinition = (InternalDefinition)existing_definition;
        SharedParameterElement para = doc.GetElement(existingInternalDefinition.Id) as SharedParameterElement;
        //delete temp shared parameter file
        doc.Application.SharedParametersFilename = sharedParameterFile;
        System.IO.File.Delete(tempSharedParameterFile);
        return para.GuidValue;
    }
    if (!categories.IsEmpty && parameterExists)
    {
        //update category list
        if (existing_binding is InstanceBinding instanceBinding)
        {
            foreach (Category c in instanceBinding.Categories)
            {
                categories.Insert(c);
            }
        }
        if (existing_binding is TypeBinding TypeBinding)
        {
            foreach (Category c in TypeBinding.Categories)
            {
                categories.Insert(c);
            }
        }
        using (Transaction trans = new Transaction(doc, "Update Parameter Categories"))
        {
            trans.Start();
            Autodesk.Revit.DB.Binding newBinding = (instance) ?
            (Autodesk.Revit.DB.Binding)doc.Application.Create.NewInstanceBinding(categories) :
            (Autodesk.Revit.DB.Binding)doc.Application.Create.NewTypeBinding(categories);
            bindingMap.ReInsert(existing_definition, newBinding, parameterGroup);
            trans.Commit();
        }
        if (existing_definition is ExternalDefinition newDefinition)
        {
            //delete temp shared parameter file
            doc.Application.SharedParametersFilename = sharedParameterFile;
            System.IO.File.Delete(tempSharedParameterFile);
            return newDefinition.GUID;
        }
    }

    #region create new parameter

    // Get the shared parameter file object
    DefinitionFile defFile = doc.Application.OpenSharedParameterFile();
    // Create a new group for the shared parameter (if it doesn't exist)
    DefinitionGroup defGroup = defFile.Groups.get_Item(groupName) ?? defFile.Groups.Create(groupName);
    // Create the shared parameter definition (if it doesn't exist)
    ExternalDefinition definition = defGroup.Definitions.get_Item(parameterName) as ExternalDefinition;
    if (definition == null)
    {
        ExternalDefinitionCreationOptions options = new ExternalDefinitionCreationOptions(parameterName, parameterType)
        {
            Visible = true
        };
        definition = defGroup.Definitions.Create(options) as ExternalDefinition;
    }

    //create an instance or type binding
    Autodesk.Revit.DB.Binding binding = (instance) ?
        (Autodesk.Revit.DB.Binding)doc.Application.Create.NewInstanceBinding(categories) :
        (Autodesk.Revit.DB.Binding)doc.Application.Create.NewTypeBinding(categories);

    // Start a transaction to add the parameter
    using (Transaction tx = new Transaction(doc, "Add Project Parameter"))
    {
        tx.Start();

        // Bind the parameter to the document
        bool added = bindingMap.Insert(definition, binding, parameterGroup);
        //apply old shared parameter file
        doc.Application.SharedParametersFilename = sharedParameterFile;
        

        if (!added)
        {
            Autodesk.Revit.UI.TaskDialog.Show("Error", "Parameter binding failed.");
            //delete temp shared parameter file
            System.IO.File.Delete(tempSharedParameterFile);
            tx.RollBack();
            return definition.GUID;
        }

        tx.Commit();
    }
    //delete temp shared parameter file
    System.IO.File.Delete(tempSharedParameterFile);
    //TaskDialog.Show("Success", "Project parameter created and bound successfully.");
    #endregion
    return definition.GUID;
}

//If a parameter exists in the project check if it is assigned to the target category
public static bool CheckParameterExistsForCategory(Document doc, Definition definition, Autodesk.Revit.DB.Binding binding, Category targetCategory)
{
    bool output_bool;
    if (binding is InstanceBinding instanceBinding)
    {
        // Check if the target category is included in the binding
        CategorySet categories = instanceBinding.Categories;
        if (categories.Cast<Category>().Any(c => c.Id == targetCategory.Id))
        {
            output_bool = true;
        }
        else
        {
            output_bool = false;
        }
    }
    else
    {
        TypeBinding typeBinding = binding as TypeBinding;
        // Check if the target category is included in the binding
        CategorySet categories = typeBinding.Categories;
        if (categories.Cast<Category>().Any(c => c.Id == targetCategory.Id))
        {
            output_bool = true;
        }
        else
        {
            output_bool = false;
        }
    }
    return output_bool;
}

//Check if a paramater with the given name already exists in the project
public static (bool, Autodesk.Revit.DB.Binding, Definition) CheckProjectParameter(Document doc, string parameterName)
{
    // Access the parameter bindings in the document
    BindingMap bindingMap = doc.ParameterBindings;
    // Iterate through the parameter bindings
    for (DefinitionBindingMapIterator iterator = bindingMap.ForwardIterator(); iterator.MoveNext();)
    {
        Definition definition = iterator.Key;
        Autodesk.Revit.DB.Binding binding = iterator.Current as Autodesk.Revit.DB.Binding;

        // Check if the parameter name matches
        if (definition.Name == parameterName)
        {
            return (true, binding, definition);
        }
    }
    return (false, null, null);
}

I am using this method (CreateProjectParameter) to create project parameters. I am calling this function from OnDocumentOpened Event. The code runs fine(means the parameters are being created) when the first document is opened. But when I close this first Document and open a second one the parameters are not being created. I am having trouble finding the problem.

0 Likes
Reply
429 Views
14 Replies
Replies (14)

sensiblehira
Enthusiast
Enthusiast

I have prepared a test file for the checking of the code, it is weird that when I open Revit and I open my test file it runs perfectly. When I close this file and open it again it doesn't work. Same is the case with any other file.

0 Likes

ctm_mka
Advocate
Advocate

Have you verified that teh "sharedParameterFile" variable is valid all the way through the code on teh second run? my guess its it getting reset somewhere, but sounds like its not throwing an error? and have you tested with a different file on the second run?

0 Likes

sensiblehira
Enthusiast
Enthusiast

tested with a second file, the error persists

0 Likes

sensiblehira
Enthusiast
Enthusiast

I also think the error is because of the shared parameter file. Let me debug this further and return with results if any.

0 Likes

scgq425
Advocate
Advocate

@sensiblehira :

 

in you code , you has use if statment to get the bool , and then use this code to change shareFile to old  file , maybe the error is : first run is create success but not run this code , and the line 154 or 146 deletd tmp file , so the second cant get a cuurrent openshareFile , you can debug this and check the second if set the current value.

 doc.Application.SharedParametersFilename = sharedParameterFile;

 

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes

sensiblehira
Enthusiast
Enthusiast

One thing is for sure when I open the second Document, my shared parameter file is not changed to the original file and the temporary file is not deleted.

0 Likes

sensiblehira
Enthusiast
Enthusiast

I verified that the code is running, but even though the code is running exactly same way in both document openings but the parameters are not there when the second document is opened

0 Likes

sensiblehira
Enthusiast
Enthusiast

I solved the issue( I mean regarding the changing of the changing of shared parameter file). But the original problem still persists.

0 Likes

sensiblehira
Enthusiast
Enthusiast

has anybody tried to recreate this issue? I can help in that case.

0 Likes

scgq425
Advocate
Advocate

Hi @sensiblehira :

has more information about the exception or just code run and nothing happend , the share parameter file and the project parameter not calling ?

so this issue is why you function cant calling about the second time to run ?

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes

sensiblehira
Enthusiast
Enthusiast

So the there were two issues, first the shared parameter file was not being changed to the original file (before the creation of parameters) while it should have. Not sure why it was not running but what I did was called TaskDialogues to see if the parameters were being created or not before the returning of their GUIDs. And the problem for the shared parameter file was resolved.(I don't know why it was not working before). but the problem with the second file opening to no parameters being created persists even though the code is running fine. Just like the when the first file is opened.

I am attaching the final version of CreateProjectParameter() for your reference. Nothing has changed in the other two methods

//Create project parameters
public static Guid CreateProjectParameter(Document doc, string parameterName,
    string groupName, ForgeTypeId parameterType, ForgeTypeId parameterGroup, bool instance,
    System.Collections.Generic.IEnumerable<Category> categoryList)
{
    // buffer the current shared parameter file name and apply a new empty parameter file instead
    string sharedParameterFile = doc.Application.SharedParametersFilename;
    string tempSharedParameterFile = System.IO.Path.GetTempFileName();
    //using (System.IO.File.Create(tempSharedParameterFile)) { }
    doc.Application.SharedParametersFilename = tempSharedParameterFile;
    //Autodesk.Revit.UI.TaskDialog.Show("Current file name", doc.Application.SharedParametersFilename);
    //check if the parameter exists
    bool parameterExists;
    Autodesk.Revit.DB.Binding existing_binding;
    Definition existing_definition;

    (parameterExists, existing_binding, existing_definition) = 
        CheckProjectParameter(doc, parameterName);

    // Get the BindingMap of the current document
    BindingMap bindingMap = doc.ParameterBindings;

    // Apply selected parameter categories
    CategorySet categories = new CategorySet();
    if (categoryList == null) //if true parameter is applied to all the categories in the document
    {
        foreach (Category c in doc.Settings.Categories)
        {
            if (parameterExists) 
            {
                if (CheckParameterExistsForCategory(doc, existing_definition, existing_binding, c))
                {
                    continue;//if the parameter exists for the category no changes are needed
                }
            }
            if (c.AllowsBoundParameters)
            {
                categories.Insert(c);//select the category if Parameter not assigned to it yet
            }
        }
    }
    else
    {
        foreach (Category c in categoryList)
        {
            if (parameterExists)
            {
                if (CheckParameterExistsForCategory(doc, existing_definition, existing_binding, c))
                {
                    continue;//if the parameter exists for the category no changes are needed
                }
            }
            if (c.AllowsBoundParameters)
            {
                categories.Insert(c);//select the category if Parameter not assigned to it yet
            }
        }
    }
    if (categories.IsEmpty) // if no category requires addition of the parameter just return the guid of existing parameter
    {
        InternalDefinition existingInternalDefinition = (InternalDefinition)existing_definition;
        SharedParameterElement para = doc.GetElement(existingInternalDefinition.Id) as SharedParameterElement;
        //delete temp shared parameter file
        doc.Application.SharedParametersFilename = sharedParameterFile;
        Autodesk.Revit.UI.TaskDialog.Show(parameterName + "Parameter Added", "Parameter already exists.");
        System.IO.File.Delete(tempSharedParameterFile);
        //Autodesk.Revit.UI.TaskDialog.Show("Current file name", doc.Application.SharedParametersFilename);
        return para.GuidValue;
    }
    else
    {
        if (parameterExists)
        {
            //update category list
            if (existing_binding is InstanceBinding instanceBinding)
            {
                foreach (Category c in instanceBinding.Categories)
                {
                    categories.Insert(c); //get categories to which the parameter is already assigned
                }
            }
            if (existing_binding is TypeBinding TypeBinding)
            {
                foreach (Category c in TypeBinding.Categories)
                {
                    categories.Insert(c); //get categories to which the parameter is already assigned
                }
            }
            using (Transaction trans = new Transaction(doc, "Update Parameter Categories"))
            {
                trans.Start();
                Autodesk.Revit.DB.Binding newBinding = (instance) ?
                (Autodesk.Revit.DB.Binding)doc.Application.Create.NewInstanceBinding(categories) :
                (Autodesk.Revit.DB.Binding)doc.Application.Create.NewTypeBinding(categories);
                bindingMap.ReInsert(existing_definition, newBinding, parameterGroup);//reassign parameter
                trans.Commit();
            }
            if (existing_definition is ExternalDefinition newDefinition)
            {
                //delete temp shared parameter file
                doc.Application.SharedParametersFilename = sharedParameterFile;
                Autodesk.Revit.UI.TaskDialog.Show(parameterName + "Parameter Added", "Parameter binding updated.");
                System.IO.File.Delete(tempSharedParameterFile);
                //Autodesk.Revit.UI.TaskDialog.Show("Current file name", doc.Application.SharedParametersFilename);
                return newDefinition.GUID;
            }
        }
    }

    #region create new parameter

    // Get the shared parameter file object
    DefinitionFile defFile = doc.Application.OpenSharedParameterFile();
    // Create a new group for the shared parameter (if it doesn't exist)
    DefinitionGroup defGroup = defFile.Groups.get_Item(groupName) ?? defFile.Groups.Create(groupName);
    // Create the shared parameter definition (if it doesn't exist)
    ExternalDefinition definition = defGroup.Definitions.get_Item(parameterName) as ExternalDefinition;
    if (definition == null)
    {
        ExternalDefinitionCreationOptions options = new ExternalDefinitionCreationOptions(parameterName, parameterType)
        {
            Visible = true
        };
        definition = defGroup.Definitions.Create(options) as ExternalDefinition;
    }

    //create an instance or type binding
    Autodesk.Revit.DB.Binding binding = instance ?
        (Autodesk.Revit.DB.Binding)doc.Application.Create.NewInstanceBinding(categories) :
        (Autodesk.Revit.DB.Binding)doc.Application.Create.NewTypeBinding(categories);

    // Start a transaction to add the parameter
    using (Transaction tx = new Transaction(doc, "Add Project Parameter"))
    {
        tx.Start();

        // Bind the parameter to the document
        bool added = bindingMap.Insert(definition, binding, parameterGroup);
        //apply old shared parameter file
        doc.Application.SharedParametersFilename = sharedParameterFile;
        

        if (!added)
        {
            Autodesk.Revit.UI.TaskDialog.Show("Error", "Parameter binding failed.");
            //delete temp shared parameter file
            System.IO.File.Delete(tempSharedParameterFile);
            tx.RollBack();
            return definition.GUID;
        }

        tx.Commit();
    }
    if (CheckProjectParameter(doc, parameterName).Item1) Autodesk.Revit.UI.TaskDialog.Show(parameterName + "Parameter Added", "new Parameter added.");
    //delete temp shared parameter file
    System.IO.File.Delete(tempSharedParameterFile);
    //TaskDialog.Show("Success", "Project parameter created and bound successfully.");
    #endregion
    //Autodesk.Revit.UI.TaskDialog.Show("Current file name", doc.Application.SharedParametersFilename);
    return definition.GUID;
}

and 

0 Likes

sensiblehira
Enthusiast
Enthusiast

this how the function is being called in my IExternalApplication class

private void OnDocumentOpened(object sender, DocumentOpenedEventArgs e)
{
    Document doc = e.Document;

    Categories categories = doc.Settings.Categories;
    Category[] categorylist = new Category[] { 
    categories.get_Item(BuiltInCategory.OST_StructuralFoundation),
                                       
    categories.get_Item(BuiltInCategory.OST_StructuralColumns)};
    Guid xguid = Miscellaneous.CreateProjectParameter(doc, "X_Coordinate", 
    "Gorilla Data", SpecTypeId.Length, GroupTypeId.Data, true, categorylist);
}

this is the version of Revit I am using = 25.2.0.38

0 Likes

scgq425
Advocate
Advocate

Hi @sensiblehira :

im so sorry not answer you question quickly .

i debug and run you new code , and open different documents more then two times , is all ok. the code push  ``add new patameter``dialog and the file deleted , the share parameter file also changed to original.

 

but when i open the document about .rvt file , is ok , and then i open the .rfa file , also push the ``add new patameter``dialog , but the share parameter file locaiton cant change to original .

 

 

 

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes

sensiblehira
Enthusiast
Enthusiast

the code is not designed for .rfa files I only want it to run on .rvt files. So I will add a condition in my code. But are you saying everything is working fine on your end with .rvt files? I mean with me the code is actually running fine but when I open to see my project parameters from the manage tab they are not there. (for the second or third document opened)

0 Likes