Холостой ход и ExternalEvent не вызываются при выборе элемента

#c# #wpf #revit-api

#c# #wpf ( ВП ) #revit-api #wpf

Вопрос:

Я создаю надстройку Revit с немодальными диалоговыми окнами WPF и хочу использовать ExternalEvent для извлечения элементов, выбранных пользователем. Является ли то, что я делаю, жизнеспособным и что мне нужно изменить, чтобы это сработало?

Поскольку у меня нет действительного контекста документа API, я вызываю ExternalEvent при нажатии кнопки, чтобы получить UniqueID элементов, которые выбраны в данный момент.

Вот соответствующие классы (я попытался сократить код настолько, насколько мог) :

 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 amp;amp; 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
  }
}
  

Когда элемент выбран, внешнее событие помечается как ожидающее, но выполняется только тогда, когда пользователь снимает флажок.

То же самое происходит с UIControlledApplication.Idling .

Я бы хотел, чтобы это выполнялось, даже когда элементы выбраны, или альтернативный способ сделать это, и не связанный с PickObject.

Комментарии:

1. Вы действительно хотите сказать, что когда набор выбранных в данный момент и выделенных элементов elements в Revit непустой, событие холостого хода никогда не запускается?

2. Я должен исправить себя в этом отношении. Он ни разу не выстрелил. Однако существуют конфигурации, в которых событие «постоянно не запускается». Похоже, это связано с тем, какие элементы выбраны. Если я возьму пример с файлом «rac_basic_sample_project.rvt», когда мое окно WPF отображается на экране, событие холостого хода не запускается при выборе крыши (ID 243274).

Ответ №1:

Я столкнулся с той же проблемой.

Я смог определить, что проблема возникает, если выбраны элементы одного семейства. Более того, существует определенное пороговое значение, где-то от 10 до 20 или более, при котором это проявляется.

Я смог обойти это, отменив выбор элементов UIDocument.Selection.SetElementIds(new List<ElementId>()) перед вызовом ExternalEvent.Raise() . А затем в конце верните выделение, если необходимо.

Комментарии:

1. У меня был совершенно другой вариант использования, но я могу подтвердить, что в определенный момент вызов Raise не приведет к выполнению внешнего обработчика событий, независимо от того, что это имеет нулевой смысл, после очистки выбора перед вызовом raise кажется, что проблема исчезла