Building Coder(Revit 二次开发) - 无模式窗口和消失的共享参数

来源:互联网 发布:网络语吃土是什么意思 编辑:程序博客网 时间:2024/05/21 03:55

Building Code 链接:http://thebuildingcoder.typepad.com/blog/2010/08/modeless-form-and-disappearance-of-shared-parameters.html

Revit 二次开发论坛:http://revit.5d6d.com/viewthread.php?tid=1301&extra=


今天的主题起因于一个共享参数的可见性问题。不过有趣的是我们最后发现它实际上是由于对 Revit API 的异步访问导致的。比方说从一个无模式对话框访问 Revit。
这个问题告诉我们从一个无效的 Revit 上下文访问 Revit 所导致的问题有时候是让人迷惑的。另外一个副产品是让我们意识到创建一个小的测试程序对查错来说是多么重要。
因为这样可以大大缩小可能的问题范围。最后是一个意外收获:有时候采用不同的交互方式会大大简化编程的复杂度和出错的可能性。在这个主题里你将看到 PickObjects
方法就能起到事半功倍的效果。

问题1:
我们需要为 Revit 模型中的某些元素添加实例参数。Revit 2011 开发指南中第270页的例子代码基本上能实现我的要求。但是在保存该模型之后,我发现在元素的属性视图中
那些新增的实例参数都消失了。但是它们依然能在共享参数视图中找到。奇怪的是相同的代码在 Revit 2010 中运行是正常的,区别只是在 Revit 2010 中新增的实例参数是
显示为项目参数的。

回答1:
创建共享参数的方法有两个重载:
1. Create(String, ParameterType)
2. Create(String, ParameterType, Boolean)
其中第二个重载版本中的 Boolean 参数用于指定该参数是否可见。我看了你的代码,注意到你在创建共享参数时使用的是第一个重载版本。我建议你使用第二个重载版本,看看
能不能解决你的问题。

另外根据 Revit 2009/2010 版本的 API 文档,创建共享参数的方法于 Revit 2011 没有差别。所以我不清楚是什么原因导致相同的代码在 Revit 2010 和 Revit 2011 中会有
不同的行为。

需要注意的是一些元素类别是不允许添加共享参数的。你可以通过 Category.AllowsBoundParameters 属性的值来判断某个元素类别是否有这个限制。

关于如何创建共享参数,请参考 Building Coder Sample 的 CmdCreateSharedParameters 外部命令。下面是该命令主要逻辑部分的代码:

  // set visibility of the new parameter:   // Category.AllowsBoundParameters property  // indicates if a category can have shared  // or project parameters. If it is false,  // it may not be bound to shared parameters  // using the BindingMap. Please note that  // non-user-visible parameters can still be  // bound to these categories.   bool visible = cat.AllowsBoundParameters;   // get or create the shared params definition:   string defname = _defname + nameSuffix.ToString();   Definition definition = group.Definitions.get_Item(    defname );   if( null == definition )  {    definition = group.Definitions.Create(      defname, _deftype, visible );  }

问题2:
我创建了一个简单的例子项目来调试我的问题。结果发现问题出在添加共享参数的代码上。我是在一个 Windows Form 中添加共享参数的。当我使用 ShowDialog() 方法
显示这个窗口时,一切都很正常。但是当我用 Show() 方法显示窗口,问题就能重现。但问题是因为业务逻辑的需要,我必须让我的窗口以非模式对话框模式显示。这样
我就能在这个窗口不关闭的情况下操作在 Reivt 用户界面和窗口之前来回切换。否则重复打开这个窗口的操作太令人厌烦了。是否有办法让我能不退出这个窗口,并且
同时在 Revit 用户界面中选择元素吗?

回答2:
我想我们找到症结所在了。Revit API 的调用需要一个有效的 Revit 上下文。通常来说 Revit 上下文只在 Revit 外部命令的 Execute() 方法中有效。其它有效的 Revit
上下文只存在于各种 Revit API 事件的处理函数中。

关于这个问题我在“无模式的松散连接器”主题中详细讨论过。简单的说,你的想法可以通过注册 Idling 事件来。你的无模式对话框不包含有效的 Revit 上下文。但是你对
该无模式对话框的操作可以通知包含有效 Revit 上下文的 Idling 事件处理器。这样下一次 Idling 事件被触发时,事件处理器就能根据用户在该无模式对话框中的操作
调用相关的 Revit API 了。

Idling 事件是由 Revit 自身在没有处理任务的情况下自动触发的。频率大致为每秒几百次。所以用户在无模式对话框中的操作应该不会有延时的感觉。

回复:
终于知道这奇怪的行为的真正原因了。十分感谢!不过我发现 PickObjects() 方法可以让用户在外部命令的上下文中交互地选择 Revit 中的元素。我只要修改一下我自己
程序的操作流程,就可以利用 PickObject() 方法简化我的实现。

回答:
没错,使用 Selection.PickObjects() 方法能让你的代码更简单可靠。我的建议是尽量避免采用无模式对话框的交互模式。关于这个方法的例子代码你可以参考我的
另一篇主题:管道转换器。

原创粉丝点击