DockablePanel with EventHandler

DockablePanel with EventHandler

NiclasSassHald
Contributor Contributor
545 Views
3 Replies
Message 1 of 4

DockablePanel with EventHandler

NiclasSassHald
Contributor
Contributor

Hi forum!

 

I'm trying to create a DockablePanel with a Page, and been following this toturial to get started: https://twentytwo.space/2020/02/23/revit-addins-dockable-window/ 

Now, when working on my own panel, i'm struggeling with an EventHandler.

I would like my panel to show some ProjectInformation - for now just the count of Warnings to see, if it updates automatic with an event like ViewActivated, DocumentChanged or so.

But when I add my EventHandler, Revit would't accept it.

 

I register my Panel on startup with this code, witch is working just fine! :

        public static void RegisterDockableWindow(UIControlledApplication app)
        {
            DockablePaneProviderData data = new DockablePaneProviderData();
            Viewer MainDockableWindow = new Viewer();

            data.FrameworkElement = MainDockableWindow as System.Windows.FrameworkElement;
            data.InitialState = new DockablePaneState();
            data.InitialState.DockPosition = DockPosition.Tabbed;
            data.InitialState.TabBehind = DockablePanes.BuiltInDockablePanes.ProjectBrowser;
            data.VisibleByDefault = true;
            DockablePaneId dpid = new DockablePaneId(new Guid("{FE19E5AC-E66B-462F-A2A5-3601458A2606}"));
            app.RegisterDockablePane(dpid, "LINK DockableWindow", MainDockableWindow as IDockablePaneProvider);
        }

Then I've been trying to add my EventHandler i my MainClass - but then it wouldn't run my code.

If I use the Loaded-event on my Page, I can add an EventHandler, and it works for me, if I open a recent project. If i browse to a folder to open another project, or create a new one, I'll get an error like: Invalid call to Revit API! Revit is currently not within an API context

My code looks like this:

        private void Viewer_Loaded(object sender, RoutedEventArgs e)
        {
            doc = ProjectModel.uiapp.ActiveUIDocument.Document;
            ProjectModel.uiapp.Application.DocumentChanged += new EventHandler<Autodesk.Revit.DB.Events.DocumentChangedEventArgs>(Application_DocumentChanged);

        }
        public void Application_DocumentChanged(object sender, DocumentChangedEventArgs e)
        {
            CollectWarnings(doc);
        }
public void CollectWarnings(Document doc)
        {
            ICollection<ElementId> failElements = new List<ElementId>();
            ICollection<ElementId> addElements = new List<ElementId>();
            IList<FailureMessage> fail = doc.GetWarnings();
            IList<string> failMessage = new List<string>();
            IList<string> failLst = new List<string>();
            int failCount = fail.Count;

            warCount.Text = failCount.ToString();
            int failEle = 0;
            string groupTxt = "";
            foreach (FailureMessage fm in fail)
            {
                failElements = fm.GetFailingElements();
                foreach (var w in failElements)
                {
                    failEle++;
                }
                failMessage.Add(fm.GetDescriptionText());
            }
            var group = failMessage.GroupBy(s => s);
            foreach (var g in group)
            {
                groupTxt += $"  [{g.Count()}] {g.Key}\n";
            }
            failLst = failMessage.Distinct().ToList();

            warTxt.Text = groupTxt;
            warElements.Text = failEle.ToString();
            warIssues.Text = failLst.Count().ToString();
        }

 

Any idea of what i'm doing wrong on this one?

 

Best Regards,

Niclas

 

0 Likes
Accepted solutions (1)
546 Views
3 Replies
Replies (3)
Message 2 of 4

ricaun
Advisor
Advisor
Accepted solution

You should never add a Revit event in the event that is not from the Revit Context, a fatal error, or the "Invalid call to Revit API! Revit is currently not within an API context" is imminent.

 

And it is a good practice when you add an event you remove when the app finishes.

 

You should register the DocumentChanged when you register the DockablePanel on the OnStartup, and make the DocumentChanged update some static variables.

 

Don't forget to remove the DocumentChanged on the OnShutdown.

 

🤘

Luiz Henrique Cassettari

ricaun.com - Revit API Developer

AppLoader EasyConduit WireInConduit ConduitMaterial CircuitName ElectricalUtils

Message 3 of 4

NiclasSassHald
Contributor
Contributor

Hi @ricaun 

Thanks for your reply!

I have struggled a bit with it, but managed to make it.

So I have created the EventHandler in: OnStartup and a method with DocumentChanged, that runs some code.

 

..and I've rembered to remove the EventHandler OnShutdown.

 

Thanks again!

Best Regards,

Niclas

Message 4 of 4

Kennan.Chen
Advocate
Advocate

You can also try Revit.Async which enables you to call Revit API from any context.