[Family] Add parameters before loaded into project

[Family] Add parameters before loaded into project

Anonymous
Not applicable
770 Views
5 Replies
Message 1 of 6

[Family] Add parameters before loaded into project

Anonymous
Not applicable

I have searched the forum and the API documentation and could not find a way to solve my problem. Here is the question:

 

I would like to create a add-in (for different users)to add parameters to the families that created by users before it loaded into project. I tried to use FamilyLoadingIntoDocumentEventArgs to achieve it.

 

private void checkFamilyAndInsertParameter(object sender, FamilyLoadingIntoDocumentEventArgs e)
        {
            string familyPath = e.FamilyPath;
            {
                Document familyDoc = e.Document.Application.OpenDocumentFile(familyPath + "//" + e.FamilyName + ".rfa");
            App.ThisApp.ShowForm(uiapp, familyDoc);

             }
         }
//*****Application Code*****

//I triger the add parameters by a button click.
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          
            _mExternalMethodWpfArg.Execute(m_app,familyDoc,UI);
            
        }

public override void Execute(UIApplication uiApp, Document familyDoc, Ui ui)
        {
            bool succeeded = Methods.AddParameters(uiApp,familyDoc,dataInputing);
        }


//here is the add parameters code:
            public static bool AddParameters(UIApplication m_app, Document familyDoc, Data data)
        {
            ParameterAssigner assigner = new ParameterAssigner(m_app.Application, familyDoc);

            using (SubTransaction t = new SubTransaction(familyDoc))
            {

                t.Start();
                succeeded = assigner.AddParameters(data);
                if (succeeded)
                {
                    t.Commit();
                    return true;
                }
                else
                {
                    t.RollBack();
                    return false;
                }
            }
        }

 

 

 No Errors, but nothing happened to the family that loaded into project. No parameters added. 

 

Anyone know why? Thanks

0 Likes
Accepted solutions (1)
771 Views
5 Replies
Replies (5)
Message 2 of 6

Anonymous
Not applicable

Additional information:

 

- I tried to use other event like DocumentSaveAs Event. The plugin works fine and parameters can be added.

- I have to use SubTransaction instead of using Transaction in FamilyLoadingIntoDocument Event, otherwise the plugin just show error.

- (Not clear)I suspect that the family I have modified is not the one it loaded into project, but I don't how to locate the one I want to loaded into project and add parameters to that.

0 Likes
Message 3 of 6

RPTHOMAS108
Mentor
Mentor

You need to clarify:

 

How your interaction with Revit is initiated i.e. is this coming from:

     IExternalCommand (Modal Window)

     ExternalEvent (Modeless Window)

What is a ParameterAssigner? I have no knowledge of this so don't know what it is doing, when it returns true and when false? You haven't elaborated on what parts of the code your debug session is reaching (does it rollback does it commit)?

 

There are more straightforward starting points from which you can then add complexity.

0 Likes
Message 4 of 6

Anonymous
Not applicable

Thanks for your reply. Your questions give me some inspiration. 

 

I use ExternalEvent:

 public class EventHandlerWithWpfArg : RevitEventWrapper<Ui>
    {
     public override void Execute(UIApplication uiApp, Document familyDoc, Ui ui)
        {
            bool succeeded = Methods.AddParameters(uiApp,familyDoc,dataInputing);
        }


        }
        
    }

 I call the showForm in IExternalApplication:

    class App : IExternalApplication
    {
        // class instance
        public static App ThisApp;

        // ModelessForm instance
        private Ui _mMyForm;

        public Result OnStartup(UIControlledApplication a)
        {
            _mMyForm = null; // no dialog needed yet; the command will bring it
            ThisApp = this; // static access to this application instance

            try
            {
                a.ControlledApplication.FamilyLoadingIntoDocument
                    += new EventHandler<Autodesk.Revit.DB.Events.FamilyLoadingIntoDocumentEventArgs>(checkFamilyAndInsertParameter);
            }
            catch
            {
                return Result.Failed;
            }

            return Result.Succeeded;
        }

        public Result OnShutdown(UIControlledApplication a)
        {
            a.ControlledApplication.FamilyLoadingIntoDocument -= checkFamilyAndInsertParameter;
            return Result.Succeeded;
        }

        public void ShowForm(UIApplication uiapp, Document fdoc, Autodesk.Revit.DB.Events.FamilyLoadingIntoDocumentEventArgs args)
        {
            // If we do not have a dialog yet, create and show it
            if (_mMyForm != null && _mMyForm == null) return;
            //EXTERNAL EVENTS WITH ARGUMENTS
            EventHandlerWithStringArg evStr = new EventHandlerWithStringArg();
            EventHandlerWithWpfArg evWpf = new EventHandlerWithWpfArg();

            // The dialog becomes the owner responsible for disposing the objects given to it.
            _mMyForm = new Ui(uiapp, fdoc, evStr, evWpf, args);
            _mMyForm.ShowDialog();
        }


private void checkFamilyAndInsertParameter(object sender, FamilyLoadingIntoDocumentEventArgs e)
        {
            string familyPath = e.FamilyPath;
            {
                Document familyDoc = e.Document.Application.OpenDocumentFile(familyPath + "//" + e.FamilyName + ".rfa");
            App.ThisApp.ShowForm(uiapp, familyDoc);

             }
         }
}

 ParameterAssigner is just a method calling familydoc.FamilyManager() to ADD parameters to the family.

 

     class ParameterAssigner
    {
        public ParameterAssigner(Autodesk.Revit.ApplicationServices.Application app, Document doc)
        {
            m_app = app;
            m_manager = doc.FamilyManager;
            m_familyParams = new Dictionary<string, FamilyParam>();
            m_assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            m_paramLoaded = false;
        }

private bool AddParameter(Data data)
        {

            foreach (DefinitionGroup group in m_sharedFile.Groups)
            {
                foreach (ExternalDefinition def in group.Definitions)
                {
                    FamilyParameter param = m_manager.get_Parameter(def.Name);
                    if (null != param)
                    {
                        continue;
                    }

                        try
                        {
                            m_manager.AddParameter(def, BuiltInParameterGroup.PG_IDENTITY_DATA, true);
                            FamilyParameter paraName = m_manager.get_Parameter(def.Name);
                            m_manager.Set(paraName, data);
                            
                        }
                        catch (System.Exception e)
                        {
                            MessageManager.MessageBuff.AppendLine(e.Message);
                            return false;
                        }
                }
            }

            return true;
        }

 

And the program successfully committed, but there is no parameters added on the family that loaded into project.

0 Likes
Message 5 of 6

Anonymous
Not applicable

My main goal is to help standardize the family (which is created by different users)  by 1)adding few parameters and value when user loaded the family into project, and 2) I will upload the family to a DMS Server. However, 1) still seems impossible to me, though it seems like just a simple task.

 

Here are some of my finding after a day of testing and debug:

 

1. FamilyLoadingIntoDocument Event and FamilyLoadedIntoDocument Event already started a transaction by Revit. You have to do a SubTransaction if you need a transaction.

 

2. The args.Document refer to the project document but not the family document

 

3. You cannot call EditFamily Method as the transaction already started...

 

Here is my simplified code for all of you to study:

 

 

 

 

 

using System;
using System.IO;
using System.Linq;
using System.Windows;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;

namespace AddParameterPlugin
{
  public class AddParameterApplication : IExternalApplication
  {
    public Result OnStartup( 
      UIControlledApplication application )
    {
      application.ControlledApplication.FamilyLoadingIntoDocument += OnFamilyLoadingIntoDocument;
      application.ControlledApplication.FamilyLoadedIntoDocument += OnFamilyLoadedIntoDocument;
      return Result.Succeeded;
    }

    public Result OnShutdown( 
      UIControlledApplication application )
    {
      application.ControlledApplication.FamilyLoadingIntoDocument -= OnFamilyLoadingIntoDocument;
      application.ControlledApplication.FamilyLoadedIntoDocument -= OnFamilyLoadedIntoDocument;
      return Result.Succeeded;
    }

    private static string GetFamilyFileName(
      FamilyLoadingIntoDocumentEventArgs e )
    {
      return string.Format( "{0}.rfa", e.FamilyName );
    }

    public static Document GetFamilyDocument(
      FamilyLoadingIntoDocumentEventArgs e )
    {
      var document = e.Document;
      var application = document.Application;

      var documents = application.Documents
        .Cast<Document>();

      string familyname = GetFamilyFileName( e );

      return string.IsNullOrWhiteSpace( e.FamilyPath )

        ? documents.FirstOrDefault(
          x =>
            string.IsNullOrWhiteSpace( x.PathName )
            && ( x.Title == e.FamilyName
              || x.Title == familyname ) )

        : documents.FirstOrDefault(
          x =>
            x.PathName == Path.Combine(
              e.FamilyPath, familyname ) );
    }

    private void OnFamilyLoadingIntoDocument(
      object sender,
      FamilyLoadingIntoDocumentEventArgs e )
    {
      var familyDocument = GetFamilyDocument( e );
      var family = familyDocument.OwnerFamily;
      var m_manager = familyDocument.FamilyManager;
       
            using (var transaction = new SubTransaction(e.Document))
            {
                transaction.Start();
                m_manager.AddParameter("test", BuiltInParameterGroup.PG_IDENTITY_DATA, ParameterType.Text, true);
                transaction.Commit();
            }

     }

 

 

 

 

 

This code can be run without any error and debug message, but the parameters cannot be added to the family loaded.

I still think that the main problem is that I added the parameters to the family which is not the one it loaded into project. But I still cannot figure out how to add it as Editfamily method(which is try to get the loaded family document) cannot be called..

0 Likes
Message 6 of 6

Anonymous
Not applicable
Accepted solution

After several try & error, I concluded that you cannot add parameters to the family when using Loaded into project event/Loading into project event. 

 

I finally solve the problem by adding a idling event (to add parameters) at the end of the Loaded into project event, and minus this idling event when finish adding the parameters. Share the information here to see if it helps anyone like me.

 

Thanks

0 Likes