Friday, December 16, 2011

Stopping save operation from Silverlight control inside CRM 2011

CRM 2011 allows to insert Silverlight controls inside forms. And when control is not just to show data, but to interact with user sometimes you may need to prevent form being saved until user finished some operation. It is quite easy to achieve in javascript, but not that obvious in Silverlight.
Let’s start. CRM 2011 SDK help gives us first clue – Xrm.Page.data.entity has addOnSave method. That’s exactly what we need. But how can we attach event to that object?
First thing to do is to get that object. As CRM 2011 SDK and Training Kit recommend us following way:

Xrm.Page.data.entity
  1. dynamic Xrm = HtmlPage.Window.GetProperty( "Xrm" ) as ScriptObject;
  2. dynamic entity = Xrm.Page.data.entity as ScriptObject;

Next step is to call addOnSave method. Handlers of OnSave method returns boolean value so lets attach some method returning boolean like this

  1. entity.Invoke( "addOnSave", new Func<bool>( OnSave ) );

But just returning bool is not enough to stop save operation. And again SDK helps us here: ExecutionObj.getEventArgs().preventDefault(). It ‘Cancels the save operation, but all remaining handlers for the event will still be executed’. ExecutionObj is something passed to the save event handler. Since we don’t know exact type of this object we will use dynamic:

Attach event
  1. entity.Invoke( "addOnSave", new Func<dynamic, bool>( OnSave ) );

And after this event handler looks like this:

Event handler
  1. private bool OnSave( dynamic eventData )
  2. {
  3.   if( !IsReadyToSave )
  4.   {
  5.     eventData.getEventArgs().preventDefault();
  6.     return false;
  7.   }
  8.  
  9.   return true;
  10. }

That’s it.
P.S. You may choose to return true instead of false when stopping save operation depending on whether you need other handlers to be executed or not. But usually false is enough
P.P.S. When your Silverlight control is inside html webresource that is after that placed on crm 2011 form, you will have to change way how you are getting Xrm reference to something like this

  1. dynamic parent = ( ScriptObject )HtmlPage.Window.GetProperty( "parent" );
  2. Xrm = parent.Xrm;