The Revit API 2012 provides an official way to extend the Element data now. In the old days, we could only create some cumbersome 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 for us 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 Extensible Storage Entity, but also at the unnecessary complexities of and many impositions by the API itself.
In this article, let us see how to store a UV type data into an Element.
Reference picked = CachedUiApp.ActiveUIDocument.Selection.PickObject(ObjectType.Element, "Pick a 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(UV));
fb1.SetUnitType(UnitType.UT_Length);
Schema schema = sb.Finish();
Entity ent = new Entity(schema);
ent.Set<UV>("FieldTest1", new UV(1.1, 2.2), DisplayUnitType.DUT_DECIMAL_INCHES);
CachedDoc.GetElement(picked).SetEntity(ent);
trans.Commit();
}
As always, the code looks like straightforward but is not at all.
First, the SetUnitType method of the newly created FieldBuilder has to be called and a UnitType be provided. Otherwise, an exception like the following would come up:
Autodesk.Revit.Exceptions.InvalidOperationException: Units are required for field FieldTest1 at Autodesk.Revit.DB.ExtensibleStorage.SchemaBuilder.Finish() …
Second, a DisplayUnitType has to be provided to the Set method with three arguments. The Set method with two arguments as commonly used by other data types is no good at all in this situation. Otherwise, another exception would happen:
Autodesk.Revit.Exceptions.ArgumentException: The displayUnits value is not compatible with the field description. …
Third, UV is nothing but a collection of two double values as I see it. Then it can also hold two scale factors, cannot it? In this case, what UnitType should we provide to the FieldBuilder.SetUnitType() method and what DisplayUnitType to the Set() method?
Fourth, since each DisplayUnitType is supposed to belong to an appropriate UnitType group as I understand it, why do we have to specify both of them in two different places? What will happen if the UnitType mismatches the DisplayUnitType?
Fifth, may these API impositions indicate that a single FieldBuilder with a UnitType can define a few fields with different DisplayUnitType values like DisplayUnitType.DUT_DECIMAL_INCHES and DisplayUnitType.DUT_METERS which belong to the same UnitType like UT_Length?
Not likely!
Sixth, with all the above confusions clarified, it would be easy to answer a question like this. If without the three looking-cool types (FieldBuilder, Schema and Entity) and all their ‘hard’ work, cannot the API get sufficient information about the field/value type, unit or any other necessary piece from the single Set() method?
Seventh, even for the Set() method, is there no way in the modern time for us to just name the value type once or not at all?
You know what I meant!
Now, let us read the same UV value back from the same Field, Entity, Schema, and Element:
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);
UV uv = ent.Get<UV>("FieldTest1", DisplayUnitType.DUT_DECIMAL_INCHES);
MessageBox.Show(string.Format("{0}, {1}", uv.U, uv.V));
trans.Commit();
}
Once again, the DisplayUnitType has to be specified in the Get() method. Otherwise, an exception would annoy us:
Autodesk.Revit.Exceptions.ArgumentException: The displayUnits value is not compatible with the field description. …
With all the matters sorted out as discussed above and demonstrated by the code snippets, the simple UV type data can finally be retrieved back.
The Revit Addin Wizard (RevitAddinWizard) is going to provide a coder to help generate Extensible Storage code.
Recent Comments