通过从 WPF DataGrid 获取的 ID 选择 Revit 元素
Selecting a Revit Element by the ID taken from WPF DataGrid
在直接跳到问题之前,我将简要描述一下我要编写的代码。基本上,我正在尝试做一个 Revit 加载项,它打开一个 WPF 对话框,显示活动视图中元素的 id
和 categoryName
,当双击包含 [= 的单元格时12=],对话框关闭,带有 id
的元素被 selected.
双击后出现问题。因为 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 class 调用的 SelectElementById(...)
方法。下面您将看到填充 DataGrid
和 MouseButtonDoubleClick
方法的功能,该方法获取单元格的值并将 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
select 某个元素?还是当前代码不允许执行此操作?
当前代码没问题。您需要获取活动视图并使用事务在当前视图中设置元素
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);
}
选择元素或某些 UI 交互不需要交易。
但是,如果您想要更改数据网格中的元素 属性 并在 revit 中应用更改,那么您将需要交易。
您可以 运行 您的 WPF window 在不同的线程上,以免阻塞 Revit UI。
然后您可以使用 IExternalEventHandler 在有效的 Revit API context
中执行代码
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
在直接跳到问题之前,我将简要描述一下我要编写的代码。基本上,我正在尝试做一个 Revit 加载项,它打开一个 WPF 对话框,显示活动视图中元素的 id
和 categoryName
,当双击包含 [= 的单元格时12=],对话框关闭,带有 id
的元素被 selected.
双击后出现问题。因为 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 class 调用的 SelectElementById(...)
方法。下面您将看到填充 DataGrid
和 MouseButtonDoubleClick
方法的功能,该方法获取单元格的值并将 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
select 某个元素?还是当前代码不允许执行此操作?
当前代码没问题。您需要获取活动视图并使用事务在当前视图中设置元素
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);
}
选择元素或某些 UI 交互不需要交易。 但是,如果您想要更改数据网格中的元素 属性 并在 revit 中应用更改,那么您将需要交易。
您可以 运行 您的 WPF window 在不同的线程上,以免阻塞 Revit UI。 然后您可以使用 IExternalEventHandler 在有效的 Revit API context
中执行代码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