我们知道Revit的一大特色功能就是关联修改,即,一处修改处处修改,比如,在三维视图修改了墙的位置,二维视图上墙的位置也跟着变化了,同时,墙上的门窗也会跟着移动。

但有时候我们有自己的特殊需求,也想做到自定义的联动关系,比如我希望两面墙的总长度是固定的,增加一面墙长度之后,另外一面墙会跟着缩减。又或者,链接文档的某个构件移动了,希望主文件的某个不相关的构件也移动。这个时候,Revit本身的关系已经不足以满足我们的需求,我们就可以使用DMU(Dynamic Model Update)了。

什么是DMU呢?简单的说,是一种事件,或者叫发布-订阅(Sub-Pub)模式,即我们在Revit里面注册一个回调函数,告诉Revit当某种类型的变动发生的时候,就调用该回调函数。

注册

先来看怎么注册。是通过UpdaterRegistry.RegisterUpdater函数,它的签名如下:

public class UpdaterRegistry : IDisposable
{public static void RegisterUpdater(IUpdater updater);public static void RegisterUpdater(IUpdater updater, bool isOptional);public static void RegisterUpdater(IUpdater updater, Document document);public static void RegisterUpdater(IUpdater updater, Document document, bool isOptional);
}

它的几个参数的含义见下表:

参数 含义
IUpdater updater 处理事件的对象,需要实现一系列的函数
bool isOptional 是否为可选,如果设为true则表示对Revit来讲可有可无,false则表示很重要,一定需要它,如果Revit启动的时候,或者打开某个文档的时候,没有找到需要的updater,Revit会弹出警告框
Document document 对应的文档,如果不指定,则表示该updater在应用级别起作用,和文档无关。如果指定了,则表示只在该文档起作用,其他文档都和它无关

实现IUpdater接口

从上面的参数中可以看到,我们需要创建一个IUpdater接口的对象,那么再来看怎么实现IUpdater接口,下面是一个例子程序:

public class ParameterUpdater : IUpdater
{UpdaterId _uid;public ParameterUpdater(Guid guid){_uid = new UpdaterId(new AddInId(new Guid("c1f5f009-8ba9-4f1d-b0fb-ba41a0f69942")), // addin idguid); // updater id}public void Execute(UpdaterData data){Func<ICollection<ElementId>, string> toString = ids => ids.Aggregate("", (ss, id) => ss + "," + id).TrimStart(',');var sb = new StringBuilder();sb.AppendLine("added:" + toString(data.GetAddedElementIds()));sb.AppendLine("modified:" + toString(data.GetModifiedElementIds()));sb.AppendLine("deleted:" + toString(data.GetDeletedElementIds()));TaskDialog.Show("Changes", sb.ToString());}public string GetAdditionalInformation(){return "N/A";}public ChangePriority GetChangePriority(){return ChangePriority.FreeStandingComponents;}public UpdaterId GetUpdaterId(){return _uid;}public string GetUpdaterName(){return "ParameterUpdater";}
}

其中比较重要的有以下几点:

  • UpdaterId的创建,第一个参数是一个Guid,该Guid是注册updater的插件的guid,必须和.addin文件里面的ClientId或AddinId一致,可能是Command也可能是Application,如下面就是该Updater的Command入口,所以第一个参数应该是c1f5f009-8ba9-4f1d-b0fb-ba41a0f69942,第二个参数是该Updater的Guid,可以使用Visual Stuido自带的工具创建一个新的。

    <?xml version="1.0" encoding="utf-8" standalone="no"?>
    <RevitAddIns><AddIn Type="Command"><Name>CommandB</Name><ClientId><span style="font-family: Arial, Helvetica, sans-serif;">c1f5f009-8ba9-4f1d-b0fb-ba41a0f69942</span><span style="font-family: Arial, Helvetica, sans-serif;"></ClientId></span><Assembly>D:\ADN\Test\bin\Debug\CommandB.dll</Assembly><FullClassName>ApplicationB.CommandB</FullClassName><VendorId>ADSK</VendorId></AddIn>
    </RevitAddIns>
  • Execute函数是主要的回调函数,它会在DMU触发的时候被调用,通过该函数的参数UpdaterData,我们可以获取很多内容,比如UpdaterData..GetDocument()可以获取Document, GetAddedElementIds()可以获取被添加的元素id。我们可以在此函数里面做很多事情,例如,修改其他元素实现关联修改。这完全可以取决于我们自己。
  • 在Execute函数里面不能使用Transaction,因为它本身就在Transaction里面
定义好IUpdater的实现类之后,我们就可以注册一个Updater对象了:
ParameterUpdater _updater = new ParameterUpdater(new Guid("{E305C880-2918-4FB0-8062-EE1FA70FABD6}"));
UpdaterRegistry.RegisterUpdater(_updater, true);

这里的Guid是使用VS自带的工具创建的

指定触发条件

最后还有一件事就是告诉Revit在什么情况下触发,需要使用AddTrigger函数,下面是它的签名:
public class UpdaterRegistry : IDisposable
{public static void AddTrigger(UpdaterId id, ElementFilter filter, ChangeType change);public static void AddTrigger(UpdaterId id, Document document, ElementFilter filter, ChangeType change);public static void AddTrigger(UpdaterId id, Document document, ICollection<ElementId> elements, ChangeType change);
}

下表是它各个参数的意义:

参数 含义
UpdaterId id Updater的id
ElementFilter filter 针对特定的元素,这些元素满足该filter的条件
ICollection<ElementId> elements 只针对这些特定的元素
Document document 只针对某个文档
ChangeType change 某种特定的修改才会触发,例如,当参数变化时(Element.GetChangeTypeParameter),或者当几何变化时(Element.GetChangeTypeGeometry),或任何变化(Element.GetChangeTypeAny)等等

如果我们想要某个Area的面积改变时触发,可以这样来写:

var parameter = element.get_Parameter(BuiltInParameter.ROOM_AREA);
UpdaterRegistry.AddTrigger(_updater.GetUpdaterId(), doc, new List<ElementId>() { new ElementId(197280)}, Element.GetChangeTypeParameter(parameter));

至此,整个DMU的流程代码都做好了,当我们改变id为197280的Area的面积的时候,Area的参数“Area"(面积)就会改变,Execute函数就会被触发。我们就可以在触发函数里面做任何我们想做的事情了。当然,还要注意,不要造成死循环了 :)

注:如果希望卸载Trigger,可以调用UpdaterRegistry.RemoveAllTriggers或者UpdaterRegistry.RemoveDocumentTriggers,卸载updater可以调用UpdaterRegistry.UnregisterUpdater

RevitAPI: 使用DMU(Dynamic Model Update)实现联动相关推荐

  1. Django model update的各种用法介绍

    Django开发过程中对表(model)的增删改查是最常用的功能之一,本文介绍笔者在使用model update过程中遇到的那些事 [ 运行环境:Django2.0 ] model update常规用 ...

  2. Dynamic Model

    Dynamic Model 0.引言 1.State-Space Model 2.Dynamic Model 3.KalmanFilter 0.引言 参考:悉尼科技大学.徐亦达老师课程. 1.Stat ...

  3. Revit二次开发之DMU

    Revit二次开发之DMU   Revit是一款三维联动的设计软件,一处修改处处修改, 比如,在三维视图修改了墙的位置,二维视图上墙的位置也跟着变化了,同时,墙上的门窗也会跟着移动. 这种联动关系是R ...

  4. Revit里模型动态更新DMU的用法

    许多时候,开发者希望Revit有这样的功能.当用户对模型进行修改后,二次开发的程序能够相应用户的修改,对模型作出一些相应的修改操作.例如,一些墙上的窗户要求永远居中显示.当用户对这个墙做了长度修改,这 ...

  5. Revit 2017 编程需要用Visual Studio2015 +.NET Framework 4.52

    一年一度的Revit产品发布时刻,我们抢先想各位介绍下Revit 2017的变化和新功能 Major changes and renovations to the Revit API API chan ...

  6. Revit启动后,如何把你的命令显示在Revit的Ribbon(工具栏)上?

    在开发的过程中,大家经常用AddinManager来运行你的外部命令,这样的好处是程序的修改,运行,调试速度可以很快. 我就此也写过一篇文章. 当你开发结束后,希望你的客户直接在Revit启动后就可以 ...

  7. 重庆大学计算机学院张玉芳是哪里人,文静(重庆大学计算机学院副教授)_百度百科...

    文静 (重庆大学计算机学院副教授) 语音 编辑 锁定 讨论 上传视频 本词条缺少概述图,补充相关内容使词条更完整,还能快速升级,赶紧来编辑吧! 文静,女,重庆大学计算机学院副教授.硕士生导师,加拿大魁 ...

  8. You can't update model without Primary Key

    com.jfinal.plugin.activerecord.ActiveRecordException: You can't update model without Primary Key, id ...

  9. Mybatis Dynamic SQL原理——更优雅的使用Mybatis

    Mybatis Dynamic SQL原理 一.Mybatis Dynamic Sql是什么 二.Mybatis Dynamic Sql原理 2.1 mybatis的本质是什么 2.2 mapper接 ...

最新文章

  1. 中科大硬核“毕业证”:“一生一芯”计划下,5位本科生带自研芯片毕业
  2. 使用python moviepy提取视频中的音频,同时对音频数据进行数据可视化分析
  3. Windows CE授权费用
  4. css为网页顶部和底部都加入背景图
  5. junit junit_使用junit做其他事情
  6. HTML如何添加锚点,分享一点面试小经验
  7. Linux下的网络桥接与链路聚合
  8. JavaScript浏览器对象模型常用事件(2)
  9. CSS 控件适配器的菜单样式解释
  10. heartbeat双机热备配置(适用centos6\rhel6)
  11. JavaWeb框架之Struts2 ---- 系列学习
  12. keil5安装_如何安装Keil5
  13. as ssd测试软件得分少,【科普贴】如何读懂AS SSD的测试数据
  14. Dos命令入侵局域网电脑
  15. 由于没有远程桌面授权服务器可以提供许可证,远程会话被中断。
  16. 破解密码——利用Windows PE操作系统破解Windows PIN
  17. 微信小游戏接入遇到的坑
  18. 蓝桥杯学习记录||1264. 动态求连续区间和 | 线段树
  19. 通过Java生成.pfx(.p12)证书文件
  20. 标准std::string分割字符串split

热门文章

  1. jap mysql注册登录_MYSQL-JAP-CRUD
  2. hdu5944Fxx and string
  3. Win10全新的图标与用户体验
  4. Hyper-V之01 恢复Hyper-V管理界面中误删除的虚拟机
  5. 利用中国区域地面气象要素驱动数据集(CMFD)和CN05.1气候数据格点化气象数据驱动Biome-BGC在区域上进行模拟
  6. Retained Messages - MQTT Essentials: Part 8
  7. 在SQL数据库中存储纬度和经度数据时要使用的数据类型是什么? [重复]
  8. [探讨]开发者眼中的PhoneGap体验
  9. Noesis: 科学家们的语义搜索引擎
  10. m4s格式转换mp3_怎么把酷狗音乐kgm格式转换成mp3格式啊