今天解决了一个问题;
这个问题之前一直困扰我,现在觉得也不是很难:
之前对着二次开发的视频来学习的,里面有这样的代码:
ElementSet elems = commandData.Application.ActiveUIDocument.Selection.Elements;
问题出就出在最后“.Selection.Elements”;
由于视频是根据Revit2011的基础上开发的,而现在的版本都有2017了;我手上的参考书上也可以这样用,但我发现书中使用的版本是Revit2014;于是我查找了一下API手册,在Revit2014中,我发现:
再看2015API:
看到最底下红色的Obsolete没有!!!!
我的老天,,当时我学这个的时候竟然没有翻手册,差点放弃治疗。。。
那么现在该如何获得选中的元素并对其进行操作呢?现在不能直接使用Selection.Elements
来获取当前选择的元素了;
下面介绍另外一个利器。。。
就是Revit2016SDK文件夹中的sample;这些都是二次开发的大神写的样例;我英语也不是太好,找到了一个类似的代码片段:
//其中m_revit就是ExternalCommandData类型对象;
bool initialize()
{
ElementSet selections = new ElementSet();
foreach (ElementId elementId in m_revit.Application.ActiveUIDocument.Selection.GetElementIds())
{
selections.Insert(m_revit.Application.ActiveUIDocument.Document.GetElement(elementId));
}
//nothing was selected
if (0 == selections.Size)
{
m_errorMessage += "Please select Basic walls";
return false;
}
//find out wall
foreach (Autodesk.Revit.DB.Element e in selections)
{
Wall wall = e as Wall;
if (null != wall)
{
if ("Basic" != wall.WallType.Kind.ToString())
{
continue;
}
m_walls.Add(wall);
}
}
//no wall was selected
if (0 == m_walls.Count)
{
m_errorMessage += "Please select Basic walls";
return false;
}
return true;
}
分析:
好吧,现在既然你不让我这样用,我只好获得选中元素的ID;然后对ID进行操作。。。
步骤:
1.我先创建一个ElementSet的对象;我查了一下API文档,这个对象是一个容器,相当于C++中的set(一种关联容器,存储的对象既是key又是value、不允许有重复的key):
-
2.开始遍历:将选中元素的ID一个一个遍历,然后用方法GetElement(ID)来得到元素;同时用insert方法将元素塞进创建的容器中;这个时候就得到了一个容器,里面都是你选择的元素了;
小挑战:
接下来,我打算写这样一个程序,来展示一下在Revit中墙的个数;这也是视频中的一个例子,我改写一下;
namespace Revit
{
[Transaction(TransactionMode.Automatic)]
[Regeneration(RegenerationOption.Manual)]
public class ArgumentUsage : IExternalCommand
{
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
ElementSet selections = new ElementSet();
ArrayList m_walls = new ArrayList();
foreach (ElementId elementId in commandData.Application.ActiveUIDocument.Selection.GetElementIds())
{
selections.Insert(commandData.Application.ActiveUIDocument.Document.GetElement(elementId));
}
foreach (Element element in selections)
{
Wall wall = element as Wall;
if (null != wall)
{
if ("Basic" != wall.WallType.Kind.ToString())
{
continue;
}
m_walls.Add(wall);
}
}
if (0 == m_walls.Count)
{
message += "Please select Basic walls";
}
else
{
String mes = string.Format("有{0}个墙被选择了", m_walls.Count);
message += mes;
}
return Result.Failed;
}
}
}
效果图:
然后,我把其中的一个墙改成了非基本墙(在Revit中的墙属性中修改),结果选择了三个再运行程序,结果如下:
这验证了我的猜想是正确的!!
补充:下面两张图片是选自2015SDK文件夹和2016SDK,sample文件夹中的一个代码片段
通过对比红色框中,可以看到,这再一次验证了selection后面已经不再支持用Elements来获取当前选择元素了;