BIM World
A Professional BIM Learning Platform


Revit API Development: Implementing Non-Modal Windows

One advantage of non-modal windows is that they can remain in front of the main program, allowing continuous operations without interruption. However, when developing secondary features in Revit, there are several important considerations for using non-modal windows:

  1. When closing the document, the non-modal window must also be closed to avoid a bug where the document closes but the window remains open.
  2. Events for non-modal windows need to be registered within IExternalCommand.
  3. All operations must be performed through an external event.

The following example focuses on the last two points, while the first can be handled through the Document event.

First, register the event within IExternalCommand:

public class Command : IExternalCommand
{
    public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
    {
        try
        {
            ExecuteEventHandler executeEventHandler = new ExecuteEventHandler("Create Model Line");
            ExternalEvent externalEvent = ExternalEvent.Create(executeEventHandler);
            // Show UI
            ModelessView modelessView = new ModelessView(executeEventHandler, externalEvent);

            // Keep the window always in front of the main program
            System.Windows.Interop.WindowInteropHelper mainUI = new System.Windows.Interop.WindowInteropHelper(modelessView);
            mainUI.Owner = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle;
            modelessView.Show();

            return Autodesk.Revit.UI.Result.Succeeded;
        }
        catch (Exception e)
        {
            message = e.Message;
            return Autodesk.Revit.UI.Result.Failed;
        }
    }
}

Next, implement a general-purpose external event handler:

public class ExecuteEventHandler : IExternalEventHandler
{
    public string Name { get; private set; }

    public Action<UIApplication> ExecuteAction { get; set; }

    public ExecuteEventHandler(string name)
    {
        Name = name;
    }

    public void Execute(UIApplication app)
    {
        if (ExecuteAction != null)
        {
            try
            {
                ExecuteAction(app);
            }
            catch
            {
                // Handle exceptions if necessary
            }
        }
    }

    public string GetName()
    {
        return Name;
    }
}

Then, create interactive components within the controls:

public partial class ModelessView : Window
{
    ExecuteEventHandler _executeEventHandler = null;
    ExternalEvent _externalEvent = null;

    public ModelessView(ExecuteEventHandler executeEventHandler, ExternalEvent externalEvent)
    {
        InitializeComponent();
        _executeEventHandler = executeEventHandler;
        _externalEvent = externalEvent;
    }

    private void creatLine_Click(object sender, RoutedEventArgs e)
    {
        if (_externalEvent != null)
        {
            _executeEventHandler.ExecuteAction = new Action<UIApplication>((app) =>
            {
                if (app.ActiveUIDocument == null || app.ActiveUIDocument.Document == null)
                    return;

                Document revitDoc = app.ActiveUIDocument.Document;
                using (Transaction transaction = new Transaction(revitDoc, "Create Line1"))
                {
                    transaction.Start();
                    Autodesk.Revit.DB.Line line = Autodesk.Revit.DB.Line.CreateBound(new XYZ(0, 0, 0), new XYZ(100, 0, 0));
                    SketchPlane sketchPlane = SketchPlane.Create(revitDoc, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero));
                    revitDoc.Create.NewModelCurve(line as Curve, sketchPlane);
                    transaction.Commit();
                }
            });
            _externalEvent.Raise();
        }
    }

    private void creatLine2_Click(object sender, RoutedEventArgs e)
    {
        if (_externalEvent != null)
        {
            _executeEventHandler.ExecuteAction = new Action<UIApplication>((app) =>
            {
                if (app.ActiveUIDocument == null || app.ActiveUIDocument.Document == null)
                    return;

                Document revitDoc = app.ActiveUIDocument.Document;
                using (Transaction transaction = new Transaction(revitDoc, "Create Line2"))
                {
                    transaction.Start();
                    Autodesk.Revit.DB.Line line = Autodesk.Revit.DB.Line.CreateBound(new XYZ(0, 100, 0), new XYZ(100, 100, 0));
                    SketchPlane sketchPlane = SketchPlane.Create(revitDoc, Plane.CreateByNormalAndOrigin(XYZ.BasisZ, XYZ.Zero));
                    revitDoc.Create.NewModelCurve(line as Curve, sketchPlane);
                    transaction.Commit();
                }
            });
            _externalEvent.Raise();
        }
    }
}

This example demonstrates a straightforward way to implement a non-modal window in Revit development.

xuebim
Follow the latest BIM developments in the architecture industry, explore innovative building technologies, and discover cutting-edge industry insights.
← Scan with WeChat
Like(0) 打赏
BIM WORLD » Revit API Development: Implementing Non-Modal Windows

Comment Get first!

Must log in before commenting!

 

BIM World, A Professional BIM Learning Platform

Stay updated on the latest architecture trends and share new building technologies.

Contact UsAbout Us

觉得文章有用就打赏一下小编吧

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

Account Login

By signing in, you agree toUser Agreement

Sign Up