Where an issue will arise is that supported method for saving records in silverlight is using either the SOAP or OData web services and the service model for silverlight is a asynchronous model. This would mean the processes would appear as follows:
- Save button is clicked.
- Save is triggered on silverlight control
- Form save is under taken
- Form is refreshed.
Because of this I have tried a number of options with no success, these include:
- Creating a javascript wait method to loop until the silverlight control is finish. The issue with this method is that the javascript and silverlight control utilise the same thread and thus all you do is cause the browser to hang indefinitely.
- Putting a wait condition on the main thread within silverlight after the async process has started and to continue waiting until the process is complete. The issue with this is the browsers main thread and the silverlight main thread are one and the same so there is nothing to tell the control that the time interval has elapse and to check again. This will also cause the browser to hang.
- Attempt to wrap the whole process up to "fake" a synchronous process. This would cause the browser to appear to hang untill the process was complete. This would partially work but not a friendly user experience.
Process is as follows:
- User clicks save button.
- Javascript calls exposed method on silverlight control.
- Silverlight control checks if anything needs saving. If so...
- Provide feedback to user that control is saving.
- Cancel the save event on the form using the "preventDefault" method provided.
- Record the save method used to save using the "getSaveMethod" JScript method.
- Save the silverlight information.
- Set the silverlight control to "clean"
- Based on the save method call the JScript "save" method on the form.
Example silverlight code:
[ScriptableMember] public bool Save(object Context) { // only save a dirty control if (IsDirty && _AllowSave) { bsyIndicator.BusyContent = "Saving Changes..."; bsyIndicator.IsBusy = true; ((dynamic)Context).preventDefault(); _SaveMode = (Constants.SaveMode)int.Parse(((dynamic)Context).getSaveMode().ToString()); // save the dirty control _recordHelper.Save_Complete += SaveComplete; _recordHelper.SaveRecord(record); return false; } IsDirty = true; return true; }
private void SaveComplete(object sender, EventArgs e) { // do nothing on callback bsyIndicator.IsBusy = false; IsDirty = false; // call save again dynamic xrm = HtmlPage.Window.GetProperty("Xrm"); switch(_SaveMode) { case Constants.SaveMode.Send: xrm.Page.data.entity.save(); break; case Constants.SaveMode.SaveClose: xrm.Page.data.entity.save("saveandclose"); break; case Constants.SaveMode.SaveNew: xrm.Page.data.entity.save("saveandnew"); break; case Constants.SaveMode.SaveCompleted: case Constants.SaveMode.Deactivate: // this is unsupported HtmlPage.Window.Invoke("SaveAsCompleted"); break; default: xrm.Page.data.entity.save(); break; } _RecordHelper.Save_Complete -= SaveComplete; }
Example JScript Code:
ExecuteSilverlightMethod = function (context, controlName, namespace, methodName) { var controlObj = Xrm.Page.ui.controls.get(controlName); silverLightControl = controlObj.getObject(); eval("silverLightControl.Content." + namespace + "." + methodName + "(context.getEventArgs());"); }
Hi, your Post is very helpful.
ReplyDeletebut there is a problem, Like you know when you Click on CRM save button it will automatically Create a Guid of the record, CreatedBy,CreatedOn, etc. but In the same time If I want to customize this record with the Name,Description,etc from silverlight It will also Create a new Guid , so we will have 2 separated record instead of One.
Hi,
DeleteThe above code will allow you to "Do something" with Silverlight when the form is saved. From what I can assume in your comment what you want to do is save some values on the current record and not on a seperate record. If this is the case simply update the fields on the form (add them to the form and make them hidden).
Use the following instead of saving a new record twice:
Xrm.Page.data.entity.attributes.get("description").setValue(description);
Xrm.Page.getAttribute("description").setSubmitMode("always");