Revit二次开发5、外部事件(ExternalEvent)
[个人学习笔记整理,若有错误请各位同仁告知]
外部事件ExternalEvent简介
事件
事件是Revit界面或API执行过程中触发的特定的动作。通过注册事件,一个插件程序能在某个动作即将发生或刚发生后得到通知,然后根据这个动作采取行动。
外部事件
Revit API提供了外部事件框架,可以用于非模式对话框。它是特别针对民步处理所开放的事件接口。它和闲置事件(IdlingEvent)处理类似,但可以由用户自己触发。
我对它的理解是:它主要用在非模态对话框窗口上,用于方便用户自己触发相应的Excute进行自己想要的操作。有了它,我们不需要每次操作都去调整Revit菜单或按钮命令,只需要在对话框窗口和Revit主窗口交互操作即可重复完成操作。
实现步骤
要使用外部事件来实现非模态对话框可以通过以下面几步来实现:
- 继承并实现外部事件处理接口(IExternalEventHandler)
- 用静态方法ExternalEvent.Create()来创建一个外部事件(ExternalEvent)
- 当非模态对话框中某个时候需要调用Revit方法时,调用ExternalEvent.Raise();
- Revit会在下个闲置时间到时来调用IExternalEventHandler.Execute()方法进行我们想要进行的操作。
外部事件的实现
实现IExternalEventHandler接口
实现这个接口的实例会被注册到Revit中,当每次相应的外部事件触发时,该接口的Execute()方法会被调用,我们写入在此Execute()中的命令会被执行,完成我们预期的操作。
IExternalEventHandler中有两个需要实现的方法:Excute()方法和GetName()方法。
Excute()用于执行相应操作。
GetName()方法返回事件的名字。
外部事件接口的定义:
public interface IExternalEventHandler
{
// 事件处理函数
void Execute( UIApplication app );
// 事件处理函数的名称
string GetName();
}
实现接口实例(以类名“EventCommand”为例 ):
public class EventCommand : IExternalEventHandler
{
public void Execute(UIApplication app)
{
UIDocument uidoc = app.ActiveUIDocument;
Document doc = uidoc.Document;
List<ElementId> elems = uidoc.Selection.GetElementIds().ToList();
using (Transaction tran = new Transaction(doc, "删除构件"))
{
tran.Start();
doc.Delete(elems);
tran.Commit();
}
}
public string GetName()
{
return "EventCommand";
}
}
ExternalEvent的创建
调用外部事件类ExternalEvent.Create()方法来创建一个外部事件,该事件所创建的一个实例会被返回给创建者,创建者可使用该实例来向Revit发信号触发事件。Revit会不时地检查否有外部事件发信号,如果接收到触发信号就会调用外部事件相应的Execute()函数。
通常做法是:
- 首先,在在对话框窗体中声明一个EventCommand(上例中的类)和一个ExternalEvent对象:
EventCommand handlerCommand = null;
ExternalEvent handlerEvent = null;
- 在对话框的加载初始化过程中,创建EventCommand实例,利用ExternalEvent.Create()方法传入EventCommand作为参数创建一个外部事件实例:
handlerCommand= new EventCommand();
handlerEvent = ExternalEvent.Create(handlerCommand);
这样,一个外部事件实例创建完成,等待被触发。
ExternalEvent的触发
调用外部事件类ExternalEvent.Raise()方法来创建一个外部事件。当它被调用后,Revit会在下一个闲置时间来调用注册好的IExternalEventHandler.Execute()方法。
- 在对话框窗口事件中,使用ExternalEvent.Raise()方法触发本次创建完成的外部事件。若有多个不同操作时,可创建多个外部事件,不同情况下(如点击不同按钮)进行不同操作:
handlerEvent.Raise();//仍以上述创建的外部事件为例
一个完整的外部事件示例
- 调用对话框窗体调用的主程序——外部命令:
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
namespace xxx
{
[Transaction(TransactionMode.Manual)]
public class MainProgram : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//利用我后面创建的对话框窗口类,创建一个对话框窗口实例
ModelessWin testwin = new ModelessWin();
//对话框窗口非模态运行
testwin.Show();
return Result.Succeeded;
}
}
}
- 实现IExternalEventHandler接口的外部事件类—EventCommand(以删除所选择的对象为例):
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using System.Collections.Generic;
using System.Linq;
namespace xxx
{
public class EventCommand : IExternalEventHandler
{
public void Execute(UIApplication app)
{
UIDocument uidoc = app.ActiveUIDocument;
Document doc = uidoc.Document;
//获取所选择对象
List<ElementId> elems = uidoc.Selection.GetElementIds().ToList();
//事务:删除所选对象
using (Transaction tran = new Transaction(doc, "删除构件"))
{
tran.Start();
doc.Delete(elems);
tran.Commit();
}
}
public string GetName()
{
return "EventCommand";
}
}
}
- 制作只有一个“删除”按钮的WPF窗体:
<Window x:Class="xxx.ModelessWin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:xxx"
Topmost="True"
Title="删除" Height="100" Width="250">
<Grid>
<Button Content="删除对象" Margin="10" Click="Button_Click" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
</Grid>
</Window>
- 补充WPF窗体代码,创建并注册外部事件,在点击删除按钮时会触发外部事件运行外部事件类—EventCommand中的Execute()方法中的操作。
using System.Windows;
using Autodesk.Revit.UI;
namespace xxx
{
/// <summary>
/// ModelessWin.xaml 的交互逻辑
/// </summary>
public partial class ModelessWin : Window
{
//补充的代码:创建外部事件
EventCommand handlerCommand = null;
ExternalEvent handlerEvent = null;
//系统代码:初始化对话框窗口
public ModelessWin()
{
InitializeComponent();
//补充代码:外部事件注册
handlerCommand = new EventCommand();
handlerEvent = ExternalEvent.Create(handlerCommand);
}
//补充代码:触发外部事件
private void Button_Click(object sender, RoutedEventArgs e)
{
handlerEvent.Raise();
}
}
}
通过上述内容,可以实现外部命令的创建和注册及调用,运行结果如下图:
在此,我们不再需要每运行一次调用一次菜单或界面按键命令,只需要不断的选择对象和点击“对话框”中的删除按钮,即可重复删除对象的操作。甚至,我们可以通过用其它动作方式来触发事件而不需要再点击对话框窗口也能重复执行命令操作;又或者,在对话框窗口设置不同的按钮或组件从而触发各种不同的操作。
.
说明:
【1】以上部分理论内容来自欧特克(中国)软件研发有限公司主编的《Autodesk REVIT二次开发基础教程》(同济大学出版社出版)。
【2】本人在对笔记的整理过程中加入了部分个人的理解与解释,希望对各位如我一样的初学者有所帮助。