选择元素时,不引发空转和ExternalEvent

时间:2019-04-01 15:13:46

标签: c# wpf revit-api

我正在使用WPF无模式对话框构建Revit加载项,并且我想使用ExternalEvent来检索用户选择的Elements。我正在做的事可行吗,我需要对其进行更改以使其起作用?

由于我没有有效的API文档上下文,因此当单击按钮以检索当前所选元素的UniqueId时,会引发ExternalEvent。

以下是相关的类(我试图尽可能地减少代码):

public class App : IExternalApplication {
  internal static App _app = null;
  public static App Instance => _app;

  public Result OnStartup(UIControlledApplication application) {
    _app = this;
    return Result.Succeeded;
  }

  public void ShowWin(UIApplication ui_app) {
    var eventHandler = new CustomEventHandler();
    var externalEvent = ExternalEvent.Create(eventHandler);
    var window = new WPFWindow(eventHandler, externalEvent);
    Process proc = Process.GetCurrentProcess();
    WindowInteropHelper helper = new WindowInteropHelper(window) {
      Owner = proc.MainWindowHandle
    };
    window.Show();
  }
}

public class AddIn : IExternalCommand {
  public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) {
    App.Instance.ShowWin(commandData.Application);
    return Result.Succeeded;
  }
}

public class CustomEventHandler : IExternalEventHandler {
  public event Action<List<string>> CustomEventHandlerDone;

  public void Execute(UIApplication ui_app) {
    UIDocument ui_doc = ui_app.ActiveUIDocument;
    if (ui_doc == null) {
      return;
    }
    Document doc = ui_doc.Document;
    List<string> element_ids = null;
    var ui_view = ui_doc.GetOpenUIViews().Where(x => x.ViewId == doc.ActiveView.Id).FirstOrDefault();
    if (doc.ActiveView is View3D view3d && ui_view != null) {
      using (Transaction tx = new Transaction(doc)) {
        tx.Start();
        element_ids = ui_doc.Selection.GetElementIds().Select(x => doc.GetElement(x)?.UniqueId).Where(x => x != null).ToList();
        tx.Commit();
      }
    }
    this.CustomEventHandlerDone?.Invoke(element_ids);
  }
}

public partial class WPFWindow {
  private CustomEventHandler _eventHandler;
  private ExternalEvent _externalEvent;

  public WPFWindow(CustomEventHandler eventHandler, ExternalEvent externalEvent) {
    this._eventHandler = eventHandler;
    this._eventHandler.CustomEventHandlerDone += this.WPFWindow_CustomEventDone;
    this._externalEvent = externalEvent;
  }

  private void Button_Click(object sender, RoutedEventArgs e) {
    this._externalEvent.Raise();
  }

  private void WPFWindow_CustomEventDone(List<string> element_ids) {
    // this point is never reached while an element is selected
  }
}

选择一个元素时,ExternalEvent被标记为待处理,但仅当用户清除选择时才执行。

UIControlledApplication.Idling也会发生同样的情况。

我希望即使在选择元素时也可以执行它,或者执行此操作的另一种方式,并且不涉及PickObject。

1 个答案:

答案 0 :(得分:0)

我遇到了同样的问题。

如果选择相同家族的元素,我可以确定是否发生了问题。而且,有一个特定的阈值,从10到20甚至更大,可以体现出来。

我能够通过在调用UIDocument.Selection.SetElementIds(new List<ElementId>())之前取消元素ExternalEvent.Raise()的选择来解决此问题。然后,如有必要,最后返回选择。