Revit二次开发之空闲事件与DocumentChanged事件解决方案

 

前段时间做Revit开发项目时遇到一个棘手的问题,我们都知道Revit运行环境是不允许多线程并发的,也就是说同一时刻只能有一个事务或操作运行,然后可以根据具体情况去触发不同的响应事件,如DocumentOpend,DocumentChanged等,那么问题是什么呢?问题是有时我们希望通过外部命令PostCommand调用Revit本身的命令,如调用绘制桥架命令,但是我们希望在此命令执行后去触发事件,后来经过测试发现PostCommand不会阻止线程的运行,而且还是外部命令运行完后才触发,那么我们就无法拿到PostCommand触发完成后的事件了,所以我们需要一个全局监控事件,来监控活动文档的改变,所以想到了DocumentChanged事件。但是发现在DocumentChanged事件里不能开始事务,也没用了,最后想到用Revit空闲事件和DocumentChanged事件相结合来做,首先我们在外部命令**册这两个事件,由DocumentChanged事件触发空闲事件,在空闲事件里执行响应的事务,最后再注销两个事件,到此问题得到有效解决。当然除了Idling还可以用ExternalEvent来做配合!

 

本代码实现调用PostCommand命令放置一个门,然后触发相应的事件再删除此门,也可以扩展其他功能,本目的就是为了测试事务是否能成功开启

Revit二次开发之空闲事件与DocumentChanged事件解决方案
 

using Autodesk.Revit.UI;

using Autodesk.Revit.DB;

using Autodesk.Revit.Attributes;

using Autodesk.Revit.UI.Selection;

using Autodesk.Revit.DB.Plumbing;

using Autodesk.Revit.DB.Mechanical;

using System.Xml;

using Autodesk.Revit.UI.Events;

 

namespace HelloWorld

{

    [Transaction(TransactionMode.Manual)]

    [Regeneration(RegenerationOption.Manual)]

    public class Test : IExternalCommand

    {  //定义一个字段通过属性变化来触发空闲事件

        public static Boolean IdleFlag = false;

        //记录DocumentChanged事件发生改变的构件

        IList listId = new List();

       //定义一个全局UIApplication,用来注销指定事件

        UIApplication uiApp = null;

        public  Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)

        {

            uiApp = commandData.Application;

            UIDocument uiDoc = uiApp.ActiveUIDocument;

            Document Doc = uiDoc.Document;

           uiApp.PostCommand(RevitCommandId.LookupPostableCommandId(PostableCommand.Door));

            uiApp.Idling += new EventHandler(IdlingHandler);

            uiApp.Application.DocumentChanged += new EventHandler(DocumentChangedForSomething);

           

            return Result.Succeeded;

        }

       

        private void DocumentChangedForSomething(object sender,Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)

        {

            listId.Clear();

            ICollection < ElementId > collection= e.GetAddedElementIds();

            listId.Add(collection.ElementAt(0));

            IdleFlag = true;

            uiApp.Application.DocumentChanged -= new EventHandler(DocumentChangedForSomething);

        }

        //Revit空闲事件

        public void IdlingHandler(object sender, IdlingEventArgs args)

        {

            UIApplication uiapp = sender as UIApplication;

            if (!IdleFlag)

            {

                return;

            }

            ExecuteIdlingHandler.Execute(uiapp, listId);

            IdleFlag = false;

            uiApp.Idling -= new EventHandler(IdlingHandler);

            

        }

    }

    public static class ExecuteIdlingHandler

    {

        public static void Execute(UIApplication uiapp,IList listId)

        {

            UIDocument uidoc = uiapp.ActiveUIDocument;

            if (uidoc != null)

            {

                Transaction ts = new Transaction(uidoc.Document, "delete");

                ts.Start();

                uidoc.Document.Delete(listId);

                ts.Commit();

               

            }

        }

 

    }

   

}