The Revit API 2012 provides an official way to extend the Element data now. In the old days, we could only create some invisible parameters and attach them to the elements where we want to store some extra data. Now the Extensible Storage API can directly address so basic a need and has much power.
Its power lies not only at that the Extensible Storage API can store various types of data ranging from the simplest such as integer and bool to quite complex such as Array and Map or even nested Entity, but also at the unnecessary complexities of and many impositions by the API itself.
We have demonstrated storing data of all allowed .NET native types by the Extensible Storage API and reading the same data back afterwards. Now let us see what ElementId storing and reading will bring to us. Here is a test external command to store three possible ElementId cases, one is invalid, another may or not be valid since an arbitrary integer value is provided to the constructor of an ElementId, and the third is good since its host Element is picked by users at a good time.
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
{
_cachedCmdData = cmdData;
try
{
//TODO: add your code below.
Reference picked = CachedUiApp.ActiveUIDocument.Selection.PickObject(ObjectType.Element,"Pick a window");
Reference picked1 = CachedUiApp.ActiveUIDocument.Selection.PickObject(ObjectType.Element, "Pick an element to store its ElementId into the window");
using (Transaction trans = new Transaction(CachedDoc, "AttachDataTo"))
{
trans.Start();
SchemaBuilder sb = new SchemaBuilder(new Guid("DA4AAE5A-4EE1-45A8-B3E8-F790C84CC44F"));
sb.SetSchemaName("SchemaTest1");
FieldBuilder fb1 = sb.AddSimpleField("FieldTest1", typeof(ElementId));
FieldBuilder fb2 = sb.AddSimpleField("FieldTest2", typeof(ElementId));
FieldBuilder fb3 = sb.AddSimpleField("FieldTest3", typeof(ElementId));
Schema schema = sb.Finish();
Entity ent = new Entity(schema);
ent.Set<ElementId>("FieldTest1", ElementId.InvalidElementId);
ent.Set<ElementId>("FieldTest2", new ElementId(123));
ent.Set<ElementId>("FieldTest3", picked1.ElementId);
CachedDoc.GetElement(picked).SetEntity(ent);
trans.Commit();
}
return Result.Succeeded;
}
catch (Exception ex)
{
msg = ex.ToString();
return Result.Failed;
}
}
Therefore, the ElementId storage of the Revit Extensible Storage API is pretty flexible. It is not bad since if people do not want the InvalidElementId or a wrong ElementId to be stored into the Schema and thus an Entity of an Element they can perform some necessary checking beforehand.
Now, let us read the three ElementId values back with the following another external command:
public Result Execute(ExternalCommandData cmdData, ref string msg, ElementSet elemSet)
{
_cachedCmdData = cmdData;
try
{
//TODO: add your code below.
Reference picked = CachedUiApp.ActiveUIDocument.Selection.PickObject(ObjectType.Element, "Pick the window having the Extensible Storage");
using (Transaction trans = new Transaction(CachedDoc, "ReadDataFrom"))
{
trans.Start();
Schema sch = Schema.Lookup(new Guid("DA4AAE5A-4EE1-45A8-B3E8-F790C84CC44F"));
Entity ent = CachedDoc.GetElement(picked).GetEntity(sch);
ElementId id1 = ent.Get<ElementId>("FieldTest1");
ElementId id2 = ent.Get<ElementId>("FieldTest2");
ElementId id3 = ent.Get<ElementId>("FieldTest3");
// To verify the element id #1
if (id1 != ElementId.InvalidElementId)
MessageBox.Show("The read-back id1 is wrong!");
// To verify the element id #2
if (id2.IntegerValue.ToString() != "123")
MessageBox.Show("The read-back id2 is wrong!");
// To verify the element id #3
if( id3 != ElementId.InvalidElementId )
CachedUiApp.ActiveUIDocument.ShowElements(id3);
trans.Commit();
}
return Result.Succeeded;
}
catch (Exception ex)
{
msg = ex.ToString();
return Result.Failed;
}
}
The external command runs smoothly after the same window is selected again. No error messages will pop up and the Element with the #3 ElementId will be properly zoomed to.
The fantastic part comes now. Please delete the picked Element, which ElementId has already been recorded in the Window as selected, and try the second external command again. What are readers expecting for at this moment? Crash? Exceptions?
No, not at all. The external command still runs without any problems. It indicates and can be verified through debugging that the #3 ElementId as stored in the selected window has been automatically and wonderfully converted to the InvalidElementId so that disasters can be avoided.
But wait, things are not done yet. What about undoing the deletion and giving the second external command one more try?
This time, the behavior may be out of people’s expectations. Instead of the Element being zoomed to, nothing happens this time. Through debugging again, we can find out that the #3 ElementId is still INVALID though apparently the Element and its ElementId have been all recovered to their original health status.
We had better keep this in mind, obviously!
The Revit Addin Wizard (RevitAddinWizard) is going to provide a coder to help generate Extensible Storage code.
Recent Comments