We recently mentioned the need to open a transaction in an event handler. In that case, the transaction was required in a handler for the document closed and saved events on the application object. Here is another similar case involving the application OnDocumentNewed event.
Question: I am trying to set up some shared parameters on OST_Rooms in a ControlledApplication. I can read and bind values from a shared parameter file, and have checked that the binding is set up correctly for the document. However, when I open the properties of a room, I don't see my parameter there. As a little background, we are creating an application to link to a database which will get and set values in the shared parameters for each room.
Answer: If you create a new document explicitly, you need to start a transaction on it. Although in this case you are not creating the new document yourself, starting a transaction solves the problem here as well:
void application_OnDocumentNewed( Document doc ) { bool rc = doc.BeginTransaction(); Debug.Assert( rc, "begin transaction failed" ); if( rc ) { CreateUserDefinedParameters( doc ); rc = doc.EndTransaction(); Debug.Assert( rc, "end transaction failed" ); } }
So, once again, you need to encapsulate the modification in a transaction. In the context of an external command, the Revit API will automatically begin a transaction for you. Depending on the IExternalCommand result value returned from the external command's Execute method, the transaction will be either closed or aborted. In all other contexts, however, including all event handlers, no such transaction will be automatically opened for you, so you are responsible for doing so yourself.
Many thanks Lindsay Rader at Advanced Technologies Group, Inc. for raising this question and to Adam Nagy of Autodesk for the answer!Rome and Cantalupo
I wrote the text above after getting hooked in a small coffee shop in Barcelona providing a wifi connection, on my way to the airport. At least I should have been on my way, instead of sitting there blogging. I very narrowly avoided missing my flight to Rome. I did make it though, checking in as the last passenger before the flight was closed, and am now on a completely uninformed and purely intuitive few-hour tour of some parts of the city. My first station here has turned out to be Viale Nino Manfredi with a fine view over the entire city. From there I took a long walk:
- through the Palatino, almost getting lost in some fenced off areas,
- around the Arco di Constantino and Colloseum,
- through a huge protest march against the Israeli warfare on Gaza,
- around the unbelievably huge and impressive Monumento di Vittorio Emmanuele II,
- through the ruins of the Teatro Marcello,
- across Isola and Fiume Tevere,
- through Trastevere, looking for a hotel and some good food,
- before spontaneously and abruptly deciding to leave Rome immediately after all.
After driving off into the unknown I ended up in a quiet and hidden little place called Cantalupo, which may or may not mean song of wolf, next to Casperia, with no idea of where I actually am, which is a very enjoyable state to be in. There is no hotel in this little town, so I am in a guest house where I first had to spend ten minutes trying to get any one electric light in the room to work. My landlady is an old lady with no teeth. She made me late supper, a delicious three-course meal from nothing, toasting some bruscetta over an open fire in the fireplace, spaghetti al'arrabiata, and cheese with some green vegetable fried in oil that she named for me but I was unable to identify or remember.
I am awakened Sunday morning at half past seven by the firing of cannons. To celebrate the fiesta of the benediction of the animals, I am told. This place is so fantastic ... in case you are interested, the address is Villa delle Rose, Viale Verdi 42, Cantalupo, Rieti, Italy, tel. 0765/514035. From here I will visit Casperia, just a few kilometres away, and then maybe continue towards Perugia, Firenze, Bologna, Verona. In case you are wondering what I am actually up to on this haphazard trip, my purpose is to teach Revit programming in Verona and learn some Italian first, with the ultimate goal of holding the training in Italian.
Well, no internet connection in Casperia, so now I am in the city of Terni, posting from the bonnet of somebody's car, hooked up to somebody's unprotected wifi.
Hi Jeremy,
Love your work. Not sure if this is the right place but just thought I'd ask for a favour...I'm having a little trouble finding a solution to a problem.
Simply put I have an app that uses Selection.PickPoint to retrieve a location from the user. I won't go into too much detail here because all works great...except for the scenario where the user may run the app (which requests a location) while a Revit command like Wall is still active.
I think what I'm looking for is a way to determine if a command/transaction is active and to terminate it.
Any ideas? Thanks in advance.
Posted by: Phil | May 01, 2012 at 05:32
Dear Phil,
Thank you for your appreciation.
The scenario you describe is utterly impossible. Or should be, at least.
If you have created such a situation, you are strongly advised to un-create it.
I suspect you are launching your command from a modeless context, so you are not in an external command at all and thus not in a valid Revit API context.
Please read the thread on modeless interaction with the Revit API and the Idling event:
http://thebuildingcoder.typepad.com/blog/idling
Here is a good entry point:
http://thebuildingcoder.typepad.com/blog/2012/01/avoid-idling.html
By the way, to answer your question, there is actually such a method as you as for:
The Application.IsQuiescent property can be used check if the current application is quiescent.
But I would not try to fix your problem using that, but rather rearchitect your situation after properly understanding the modeless interaction issues.
Cheers, Jeremy.
Posted by: Jeremy Tammik | May 01, 2012 at 06:18
Thanks Jeremy, you are correct and thanks for the info. I'll follow it and re-design.
Cheers
Phil
Posted by: Phil | May 04, 2012 at 16:07
Thanks again for the info and helps to explain the major concerns with modeless apps. I hear the warnings.
The app that I'm building is essentially a space management tool where a user can place one or more room elements by selecting from a databound treeview control, pre-poulating parameters and allowing some management of room areas. Also creates a 'connection' between each room element and it's corresponding record in the database.
As I mentioned, this works very well in all testing to date (more to do), except where a Revit command is started while the dialog is open, and then try to place a room from the treeview while that command is still active. This consistently shuts Revit without warning!!
Through testing there have been other situations that had the same reult but these were programming bugs and seem resolved.
I'll re-visit the design, particularly in 2013 and beyond but for now I've created a handler for the documentChanged event to pick up when the user is editing the model and to politely close the dialog. Functionally, this is fine. For safety and consistency, I've created handlers for the other events to do the same.
I know, I'm breaking some rules but I think the development is well worth persisting with, particularly since it's highly functional and very user friendly - and part of a bigger solution outside Revit.
BTW, I'm not using the Idling event, and Application.IsQuiescent always returns false in this case.
Thanks again, Cheers.
Posted by: Phil | May 05, 2012 at 18:35
Dear Phil,
Glad to hear you have it working and are happy with it.
I would still recommend checking out the Revit 2013 ModelessForm_ExternalEvent and ModelessForm_IdlingEvent SDK samples and rewriting your application using the architecture demonstrated there. That would make it nore future proof, and the ModelessForm_IdlingEvent approach would work for Revit 2012 as well as 2013.
Cheers, Jeremy.
Posted by: Jeremy Tammik | May 06, 2012 at 14:50
Shall do...thanks!
Posted by: Phil | May 14, 2012 at 09:48