Getting doc and application when not starting from external command - dockable pane

Getting doc and application when not starting from external command - dockable pane

Kevin.Bell
Advisor Advisor
1,079 Views
4 Replies
Message 1 of 5

Getting doc and application when not starting from external command - dockable pane

Kevin.Bell
Advisor
Advisor

Hi,

 

I've created an addin that has a dockable pane and allow the user to open certain views by clicking on buttons in the pane.

 

When I first load the addin after compiling it from Visual Studio the pane does not appear, I then have to click on the ribbon button I've created which loads the pane - this uses an external command and ExternalCommandData obtains the active document etc via:  UIApplication uiapp = commandData.Application;

 

But then when I close Revit and reopen it, the pane is automatically displayed (the user does not have to press the ribbon button) - but this means I can't grab UIApplicaiton from commandData and cannot get the active document.

 

Is there any way I can directly get the active document?

 

Thanks,

0 Likes
Accepted solutions (1)
1,080 Views
4 Replies
Replies (4)
Message 2 of 5

RPTHOMAS108
Mentor
Mentor
Accepted solution

Ordinarily you would raise an ExternalEvent for this purpose and it would give you those objects.

 

If you review the samples within the SDK you'll come across this:

 

...\ModelessDialog\ModelessForm_ExternalEvent

...\DockableDialogs

0 Likes
Message 3 of 5

Kevin.Bell
Advisor
Advisor

Perfect - Thanks!

0 Likes
Message 4 of 5

Kevin.Bell
Advisor
Advisor

Ok, I've now set up an external event to recieve UIApplication, this works, but the event which retrieves UIApplication is executed after my code runs - consiquently UIApplication is null and I get an exception.

 

My test code is this, I've created a modeless form, the form has a property called 'retrievedUIapp' which is null.

 

When the button is pressed, a message is displayed showing the current value of retrievedUIapp (which is null), then the event is raised, then another message is displayed showing the new value of retrievedUIapp which should show what was returned from the event.

 

The code is:

 

Command.cs

 

    public class Command : IExternalCommand
    {
        public Result Execute(
          ExternalCommandData commandData,
          ref string message,
          ElementSet elements)
        {
            Form1 myModelessDialog = new Form1();

            myModelessDialog.Show();

            return Result.Succeeded;
        }
    }

 

 

 The form with button:

 

 

namespace GetDocXEvent
{
    public partial class Form1 : System.Windows.Forms.Form
    {
        private myAddon.EventHandlerWithStringArg myEvent
        {
            get;
            set;
        }

        public Form1()
        {
            InitializeComponent();

            myEvent = new myAddon.EventHandlerWithStringArg();

        }

        public static UIApplication retrievedUIAPP
        {
            get;
            set;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //A blank string which will hold the current uiapp to sting
            string uiapptostring;

            //Check the retrievedUIAPP, if its null then set string to null if not then set string to uiapp to string.
            if (retrievedUIAPP == null)
            {
                uiapptostring = "null";
            }
            else
            {
                uiapptostring = retrievedUIAPP.ToString();
            }

            //Display message showing current value of UIAPP
            TaskDialog.Show("Message", "Button Pressed... Raising external event\nUIApplication is " + uiapptostring);

            //Raise event
            myEvent.Raise("this is an argument");

            //Check the retrievedUIAPP, if its null then set string to null if not then set string to uiapp to string.
            if (retrievedUIAPP == null)
            {
                uiapptostring = "null";
            }
            else
            {
                uiapptostring = retrievedUIAPP.ToString();
            }

            //Display message showing what UIAPP is now
            TaskDialog.Show("Message", "Finished\nUIApplication is " + uiapptostring);
        }
    }
}

 

 

 

External event code:

 

    public partial class myAddon 
    {
        //https://thebuildingcoder.typepad.com/blog/2018/04/revit-20183-setvaluestring-and-external-events.html#4

        abstract public class RevitEventWrapper<T> : IExternalEventHandler
        {
            private object @lock;
            private T savedArgs;
            private ExternalEvent revitEvent;

            public RevitEventWrapper()
            {
                revitEvent = ExternalEvent.Create(this);
                @lock = new object();
            }

            public void Execute(UIApplication app)
            {
                T args;

                lock (@lock)
                {
                    args = savedArgs;
                    savedArgs = default(T);
                }
                Execute(app, args);
            }

            public string GetName()
            {
                return GetType().Name;
            }

            public void Raise(T args)
            {
                lock (@lock)
                {
                    savedArgs = args;
                }
                revitEvent.Raise();
            }

            abstract public void Execute(UIApplication app, T args);
        }

        public class EventHandlerWithStringArg : RevitEventWrapper<string>
        {
            public override void Execute(
              UIApplication uiApp,
              string args)
            {
                //Display message to show event is running and value of uiapp
                TaskDialog.Show("Message", "From external event - uiApplication is " + uiApp.ToString());

                //Set recievedUIAPP variable in form
                Form1.retrievedUIAPP = uiApp;
            }
        }

    }

 

Attached is a zip of the code.

 

The external event code came from @jeremytammik 

 

Is there any way I can get my code to wait for the external event to be returned? Or am I going about this the wrong way!

 

Thanks.

 

0 Likes
Message 5 of 5

jeremytammik
Autodesk
Autodesk

Please just start from scratch using an existing working example.

 

For instance, a good starting point is provided by the ModelessDialog/ModelessForm_ExternalEvent Revit SDK sample.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes