Here is a little issue with an interesting workaround that I encountered in the past in similar incarnations in other CAD software packages besides Revit, so it is worthwhile making a note of this for potential future use almost anywhere.
The issue has to do with refreshing the graphics display of individual elements in the Revit user interface.
Committing the transaction, explicit regeneration, and even calling RefreshActiveView does not help. One additional thing that sometimes does help in similar situations is saving the document, but that is obviously a last recourse.
The interesting workaround presented in this case suggests moving the affected elements by a certain amount using ElementTransformUtils.MoveElement, and then moving them back again.
One place where I used similar tricks in the past was in the AutoCAD ARX API, where you could trigger a regeneration of an entity by calling transformBy with an identity matrix on it, if nothing else helped.
Here is the context of the issue:
Question: I'm importing a DWG into a Revit family. It contains a solid filled polygon on one layer.
I am trying to change its line colour via its sub-category.
Using the following code in VSTA changes the Object Style properly, and I can see the change in the Object Styles dialog:
public void ObjectStyleTest() { UIDocument uiDoc = this.ActiveUIDocument; Document doc = this.ActiveUIDocument.Document; Transaction tr = new Transaction( doc ); tr.Start( "ObjectStyles" ); Category cat = doc.Settings.Categories.get_Item( BuiltInCategory.OST_ImportObjectStyles ); Category subCat = cat.SubCategories.get_Item( "A--A28--_F-2--" ); subCat.LineColor = new Color( 0, 0, 255 ); doc.Regenerate(); tr.Commit(); uiDoc.RefreshActiveView(); }
However, the already existing ImportInstance does not change colour as expected. If I change the ObjectStyle colour in the user interface, then the ImportInstance does change colour.
I tried calling Regenerate and RefreshActiveView, but they have no effect. Once I move the ImportInstance in the user interface, its colour updates properly.
Answer: You can solve this programmatically, but you need to use a little workaround. One possible workaround is to move the elements back and forth a bit. Here is your sample code enhanced to show how to do this:
public void ChangeImportedCategoryColor( UIDocument uiDoc ) { Document doc = uiDoc.Document; Transaction tr = new Transaction( doc ); tr.Start( "ObjectStyles" ); Category cat = doc.Settings.Categories.get_Item( BuiltInCategory.OST_ImportObjectStyles ); Category subCat = cat.SubCategories.get_Item( "A--A28--_F-2--" ); subCat.LineColor = new Color( 0, 0, 255 ); // <workaround> FilteredElementCollector coll = new FilteredElementCollector( doc ) .OfClass( typeof( ImportInstance ) ); foreach( Element e in coll ) { ElementTransformUtils.MoveElement( doc, e.Id, XYZ.BasisX ); ElementTransformUtils.MoveElement( doc, e.Id, XYZ.BasisX.Negate() ); } // </workaround> tr.Commit(); }
As said, in a similar situation in AutoCAD, it was sufficient to call transformBy with an identity transformation. I tried out whether it works making just one single call to MoveElement with a XYZ.Zero argument, instead of two, but that is not the case. I also tested changing some element parameter values back and forth, but since that does not change the geometry (I guess) it did not do the trick.
Many thanks to Harry Mattison and Adam Nagy for providing this idea!
Addendum: As Rudolf points out in his comment below, this workaround may need to be adjusted for hosted elements:
Moving windows or doors may cause errors if the translation is too large, causing the element to leave its host boundaries, or if the moving direction is locked for the element. For example, windows cannot be moved in the Wall.Orientation direction.
Therefore, it would be safer to move the elements by just a tiny amount instead of a whole foot, and also ensure that the movement direction is parallel to the host face. For example, for a window in a vertical wall, you might use XYZ.BasisZ.Multiply(tinyAmount) instead of XYZ.BasisX.
Hi Jeremy,
this workaround may be adjusted for hosted elements.
Moving windows or doors may cause errors if the translation is too large (element would leave its host's boundaries) or if the moving direction is locked for the element. For example, windows cannot be moved into the Wall.Orientation direction.
For windows, XYZ.BasisX may be replaced by XYZ.BasisZ.Multiply(tinyAmount).
Posted by: Rudolf Honke | July 07, 2011 at 04:51
Dear Rudolf,
Thank you very much for that very valid comment! So important that I added it above as well, to ensure it is not missed, in case of just reading the main section and skipping the comments.
Cheers, Jeremy.
Posted by: Jeremy Tammik | July 07, 2011 at 05:17
Hi Jeremy,
additionally, if the element is a rooflight, the moving vector is depending on the roof's normal vector.
Moreover, thinking of a window hosted in a FaceWall which can be bent in two directions.
There would be a different moving vector for each possible LocationPoint. After you have moved the Element from A to B using a vector that is valid for moving from point A, just this vector, negated, may be inappropriate for moving the element back from B to A because it is not a valid moving vector regarding point B.
Hope I expressed it the right way.
Posted by: Rudolf Honke | July 07, 2011 at 06:01
Dear Rudolf,
Sure, I see what you mean.
Considering the complexities of moving hosted elements along curved surfaces, it might be worth while checking whether some other element modification may be easier to accomplish, if this functionality is important to you. Maybe something like temporarily changing the type might also work.
Cheers, Jeremy.
Posted by: Jeremy Tammik | July 07, 2011 at 06:14
Hi Jeremy,
This is off what is being discussed but i need help with this. I am created a navisworks plugin which will enable me connect to a web interface and get some data. The problem is that the plugin will not load into navisworks. How do i find my way around this?
Posted by: Demmy | October 14, 2011 at 19:53
Dear Demmy,
Sorry, I have no idea about Navisworks at all. Please submit a case through the Autodesk Developer Network ADN DevHelp Online, if you are a member, or try one of the Autodesk discussion groups or some other peer forum if not:
http://thebuildingcoder.typepad.com/blog/2009/10/revit-api-forums.html
Good luck!
Cheers, Jeremy.
Posted by: Jeremy Tammik | October 16, 2011 at 08:13