【问题标题】:Selecting a Revit Element by the ID taken from WPF DataGrid通过取自 WPF DataGrid 的 ID 选择 Revit 元素
【发布时间】:2021-05-31 03:29:05
【问题描述】:

在直接讨论问题之前,我将简要介绍一下我要编写的代码。基本上,我正在尝试做一个 Revit 加载项,它打开一个 WPF 对话框,显示活动视图中元素的idcategoryName,当双击包含id 的单元格时,对话框关闭并选择带有id 的元素。

双击后出现问题。因为Execute() 命令在显示对话框后结束,所以我不再能够执行Selection

Command.cs

[Transaction(TransactionMode.Manual)]
   public class Command : IExternalCommand
   {
      static List<Element> elemList = new List<Element>();

      public Result Execute(
        ExternalCommandData commandData,
        ref string message,
        ElementSet elements)
      {
         UIApplication uiapp = commandData.Application;
         UIDocument uidoc = uiapp.ActiveUIDocument;
         Application app = uiapp.Application;
         Document doc = uidoc.Document;

         //List<Element> elemList = new List<Element>();

         FilteredElementCollector allElementsInView = new FilteredElementCollector(doc, doc.ActiveView.Id);
         IList elementsInView = (IList)allElementsInView.ToElements();

         foreach (Element elem in elementsInView)
         {
            elemList.Add(elem);
         }

         OpenDialog();

         return Result.Succeeded;
      }
      
      public static void SelectElementById(ElementId id)
      {

      }

      public static List<Element> SendElements()
      {
         return elemList;
      }

      public void OpenDialog()
      {
         ElementListDialog dialog = new ElementListDialog();

         dialog.Show();
      }

   }
}

正如您在上面看到的,我还有一个从 ElementListDialog.xaml.cs 类调用的 SelectElementById(...) 方法。下面您将看到填充DataGridMouseButtonDoubleClick 方法的功能,该方法获取单元格的值并将ElementId 类型的id 传递回Command.cs

ElementListDialog.xaml.cs

private List<Element> elemList;
      public ElementListDialog()
      {
         InitializeComponent();
         Lab8.Command.SendElements();
         elemList = Lab8.Command.SendElements();

         //elemList = _elemList;

         Content content = new Content();

         foreach (var elem in elemList)
         {
            content = new Content();
            content.id = elem.Id;
            content.categName = elem.Category.Name;

            var finalList = new Content
            {
               id = content.id,
               categName = content.categName
            };
            
            ElementDataGrid.Items.Add(finalList);
            
         }
      }

      private void ElementDataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
      {
         var grid = sender as DataGrid;

         var cellValue = grid.SelectedValue;
         Content content = new Content();

         content = (Content)cellValue;
         
         Command.SelectElementById(content.id);
      }

因此;我应该如何设计SelectElementById 方法,以便能够通过id 选择某个元素?还是当前代码不允许执行此操作?

【问题讨论】:

    标签: c# wpf revit-api


    【解决方案1】:

    当前代码没问题。您需要获取活动视图并使用事务在当前视图中设置元素

    public static void SelectElementById(ElementId id)
        {
            ICollection<ElementId> to_showids = new List<ElementId>();
            to_showids.Add(id);
    
            //RESET ELEMENTS IN VIEW
            var itrans = new Transaction(YOURDOCUMENT, "Show Element");
            using(itrans)
            {
                itrans.Start();
                //The below step is to make sure that any previous selection is removed and only your new selection is set.
                YOURDOC_UI.Selection.SetElementIds(to_showids);
                itrans.Commit();
            }
    
            //SHOW ELEMENTS
            YOURDOC_UI.ShowElements(to_showids);
        }
    

    【讨论】:

    • 非常感谢您的帮助!但是,我不知道如何从Execute 方法调用YOURDOCUMENTYOURDOC_UI。有什么建议吗?
    • 我自己尝试了一些东西,但在itrans.Start(); 上出现此错误:Autodesk.Revit.Exceptions.InvalidOperationException: 'Starting a transaction from an external application running outside of API context is not allowed.'
    • 我删除了交易并且运行良好。再次感谢您的帮助!我仍然很好奇如何让它与交易一起使用?
    • YOURDOCUMENT 和 YOURDOC_UI 基本上是占位符。你需要你的 UIDocument 和 Document 。您可以将它们存储在任何静态属性中(以便可以全局访问)。当您调用您的 IExternalApplication 时,您将获得该文档并可以存储它们。
    • 就事务而言,我没有注意到对话框关闭然后调用该方法(这使得它在 API 上下文之外)。可能您可以创建具有 Action 或 Func 属性的通用命令。在每次调用命令之前,您可以使用您的实际方法设置这些委托属性并调用它们。这样所有调用都在 Revit API 上下文中。
    【解决方案2】:

    选择元素或某些 UI 交互不需要事务。 但是,如果您想更改 datagrid 中的元素属性并在 revit 中应用更改,那么您将需要事务。

    您可以在不同的线程上运行 WPF 窗口,以免阻塞 Revit UI。 然后您可以使用 IExternalEventHandler 在有效的 Revit API 上下文中执行代码

    class DoSomethingOnEventRaised : IExternalEventHandler
    {
        public void Execute(UIApplication uiapp)
        {
            //code to be executed in API context
        }
    }
    
    IExternalEventHandler doSomethingEvHandler = new DoSomethingOnEventRaised();
    ExternalEvent doSomethingEvent = ExternalEvent.Create(calculationSupport);
    
    doSomethingEvent.Raise() will execute the code
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-29
      • 1970-01-01
      相关资源
      最近更新 更多