Current filter:
                                You should refresh the page.
                                  • -----------------------------------------------
                                    The Mobile UI is in maintenance mode. However, our installation still includes the Mobile UI. We continue to provide support and fix critical bugs, but we do not create new features. Once the new SPA UI is mature, it should cover all the Mobile UI scenarios and also provide new functionality. Refer to the New XAF HTML5/JavaScript SPA UI for Web & Mobile (CTP) KB article for more information on the SPA UI.
                                    We've created a KB article that describes how to save a manually drawn signature to an object's image property using the Signature Pad JavaScript library.  We'll show you how to include the custom control's source code and styles in your mobile application and implement an Action in a DetailView to show a popup dialog with a signature pad.

                                    UPDATED (Aug 1, 2018):
                                    An actual API is now used for the dxPopup control.
                                    UPDATED (Apr 9, 2018):
                                    Starting with v17.2.8, MobilePropertyEditor supports the Edit ViewEditMode. We updated our How to use a Signature Pad in XAF Mobile example and enabled SignatureAction in the Edit mode accordingly. This improvement saves end-users time not only for this particular scenario (they no longer require to switch views), but also when working with regular image properties.
                                    For early testing, we published a daily build. You can download it using the following link: DevExpressNETComponents-

                                    Install any v17.2.3+ version.

                                    Steps to implement
                                    1.  In the YourSolutionName.Mobile project, follow the first four steps from How to: Add an XAF Mobile Custom Module to create a new custom Mobile module, and name it sigpad  (do not forget to use the same name when registering the module in the MobileApplication.CustomizeApplicationConfig event handler in the fourth step of this article).

                                    To finish with the custom module creation for this particular example,  do the following:
                                     - exclude or remove the template.html file;
                                     - rename widget.css to sigpad.css;
                                     - add a new sigpad.js file;
                                     - modify the module.json file as follows:

                                    { "main": "widget.js", "files": [ "sigpad.css", "sigpad.js" ] }

                                    After these preparations, the YourSolutionName.Mobile project's Static/Modules/sigpad folder structure may look as follows:

                                    In the next two steps, we will modify the custom module's scripts and styles to provide a required behavior and appearance.
                                    2.  Put the contents of the plugin's source code file to the custom module's sigpad.js and put the contents of the plugin's styles file to the custom module's sigpad.css respectively. Of course, you are free to modify the original plugin's files as your business needs dictate, e.g., you can remove unnecessary styles from it (for body, github etc.).
                                    Please note that we have changed the following line in sigpad.js:

                                    function SignaturePad(canvas, options) {


                                    window.SignaturePad = function (canvas, options) {

                                    3.  Put the following code to the custom module's widget.js file (its base part is located here):

                                    window.showSignaturePad = function (viewModel, signaturePropertyName) { var getContentTemplate = function () { return $(`<div id="signature-pad" class="signature-pad"> <div class="signature-pad--body"> <canvas></canvas> </div> <div class="signature-pad--footer"> <div class="description">Sign above</div> </div> </div>`); }; var viewPortSelector = ".dx-viewport"; var getCalculatedPopupSize = function () { var viewPort = $(viewPortSelector)[0]; var popupWidth = viewPort.clientWidth * 0.9; var popupHeight = viewPort.clientHeight * 0.9; return { width: popupWidth, height: popupHeight }; }; var popupSize = getCalculatedPopupSize(); var popupOptions = { width: popupSize.width, height: popupSize.height, contentTemplate: getContentTemplate, showTitle: true, title: "Signature", visible: false, dragEnabled: false, closeOnOutsideClick: true, toolbarItems: [ { toolbar: 'bottom', location: 'before', widget: 'button', options: { text: 'Clear', onClick: function (e) { signaturePad.clear(); } } }, { toolbar: 'bottom', location: 'after', widget: 'button', options: { text: 'Save', onClick: function () { if (signaturePad.isEmpty()) { DevExpress.ui.notify({ closeOnClick: true, message: 'Please provide a signature first', type: 'error' }, 'error', 5000); } else { var dataURL = signaturePad.toDataURL(); var imageData = dataURL.replace("data:image/png;base64,", ""); var signatureDataSourcePropertyName = signaturePropertyName + "DataSource"; viewModel[signatureDataSourcePropertyName] = imageData; window.signaturePopup.hide(); } } } } ], }; if (window.signaturePopup) { $(".signaturepopup").remove(); } var $popupContainer = $("<div />") .addClass("signaturepopup") .appendTo($(viewPortSelector)); window.signaturePopup = $popupContainer.dxPopup(popupOptions).dxPopup("instance");; var wrapper = document.getElementById("signature-pad"); var canvas = wrapper.querySelector("canvas"); var signaturePad = new SignaturePad(canvas, { // It's Necessary to use an opaque color when saving image as JPEG; // this option can be omitted if only saving as PNG or SVG backgroundColor: 'rgb(255, 255, 255)' }); // Adjust canvas coordinate space taking into account pixel ratio, // to make it look crisp on mobile devices. // This also causes canvas to be cleared. function resizeCanvas() { // When zoomed out to less than 100%, for some very strange reason, // some browsers report devicePixelRatio as less than 1 // and only part of the canvas is cleared then. var ratio = Math.max(window.devicePixelRatio || 1, 1); // This part causes the canvas to be cleared canvas.width = canvas.offsetWidth * ratio; canvas.height = canvas.offsetHeight * ratio; canvas.getContext("2d").scale(ratio, ratio); // This library does not listen for canvas changes, so after the canvas is automatically // cleared by the browser, SignaturePad#isEmpty might still return false, even though the // canvas looks empty, because the internal data of this library wasn't cleared. To make sure // that the state of this library is consistent with visual state of the canvas, you // have to clear it manually. signaturePad.clear(); } // On mobile devices it might make more sense to listen to orientation change, // rather than window resize events. //window.onresize = resizeCanvas; resizeCanvas(); DevExpress.devices.on("orientationChanged", function (e) { var popupSize = getCalculatedPopupSize(); window.signaturePopup.option("width", popupSize.width); window.signaturePopup.option("height", popupSize.height); resizeCanvas(); }); };

                                    In this code, we create an HTML template for a popup dialog (dxPopup) and show it. Please tale note of the Save button's onClick handler in this dialog where the signature is saved to the business object's Signature property (we will define it in the next step).The orientationChanged DevExtreme event is used to detect screen orientation changes.
                                    4. In the YourSolutionName.Module project's BusinessObjects folder, create a business object with a byte array property called Signature:

                                    using DevExpress.Persistent.Base; using DevExpress.Persistent.BaseImpl; using DevExpress.Xpo; using System.Drawing; namespace ExampleProject.Module.BusinessObjects { [DefaultClassOptions] public class Registration : BaseObject { public Registration(Session session) : base(session) { } private string name; public string Name { get { return name; } set { SetPropertyValue("Name", ref name, value); } } private byte[] signature; [Size(SizeAttribute.Unlimited)] [ImageEditor] public byte[] Signature { get { return this.signature; } set { this.SetPropertyValue<byte[]>("Signature", ref this.signature, value); } } } }
                                    Imports DevExpress.Persistent.Base Imports DevExpress.Persistent.BaseImpl Imports DevExpress.Xpo Imports System.Drawing Namespace ExampleProject.Module.BusinessObjects <DefaultClassOptions> Public Class Registration Inherits BaseObject Public Sub New(ByVal session As Session) MyBase.New(session) End Sub Private name_Renamed As String Public Property Name() As String Get Return name_Renamed End Get Set(ByVal value As String) SetPropertyValue("Name", name_Renamed, value) End Set End Property Private signature_Renamed() As Byte <Size(SizeAttribute.Unlimited), ImageEditor> Public Property Signature() As Byte() Get Return Me.signature_Renamed End Get Set(ByVal value As Byte()) Me.SetPropertyValue(Of Byte())("Signature", Me.signature_Renamed, value) End Set End Property End Class End Namespace

                                    Please take note of the attributes of the image property and learn more about them in our documentation.

                                    5.  In the YourSolutionName.Module.Mobile project's Controllers folder, create a ViewController which creates a SimpleAction for a Registration's Detail View. The Action will be only available in a view mode of this DetailView like the MobileImagePropertEditor.

                                    using DevExpress.ExpressApp; using DevExpress.ExpressApp.Actions; using DevExpress.Persistent.Base; using ExampleProject.Module.BusinessObjects; namespace ExampleProject.Module.Mobile.Controllers { public class SignaturePadController : ObjectViewController<DetailView, Registration> { public const string EnabledInEditMode = "EnabledInEditMode"; private SimpleAction signatureAction; public SignaturePadController() { signatureAction = new SimpleAction(this, "Signature", PredefinedCategory.Edit); signatureAction.ImageName = "User"; signatureAction.RegisterClientScriptOnExecute("ScanScript", GetBarCodeClientScript()); } protected override void OnActivated() { base.OnActivated(); signatureAction.Enabled[EnabledInEditMode] = View.ViewEditMode == DevExpress.ExpressApp.Editors.ViewEditMode.Edit; } protected string GetBarCodeClientScript() { return string.Format(@"window.showSignaturePad($model, '{0}');", nameof(Registration.Signature)); } public SimpleAction SignatureAction { get { return signatureAction; } } } }
                                    Imports DevExpress.ExpressApp Imports DevExpress.ExpressApp.Actions Imports DevExpress.Persistent.Base Imports ExampleProject.Module.BusinessObjects Namespace ExampleProject.Module.Mobile.Controllers Public Class SignaturePadController Inherits ObjectViewController(Of DetailView, Registration) Public Const EnabledInEditMode As String = "EnabledInEditMode" Private signatureAction_Renamed As SimpleAction Public Sub New() signatureAction_Renamed = New SimpleAction(Me, "Signature", PredefinedCategory.Edit) signatureAction_Renamed.ImageName = "User" signatureAction_Renamed.RegisterClientScriptOnExecute("ScanScript", GetBarCodeClientScript()) End Sub Protected Overrides Sub OnActivated() MyBase.OnActivated() signatureAction_Renamed.Enabled(EnabledInEditMode) = View.ViewEditMode = DevExpress.ExpressApp.Editors.ViewEditMode.Edit End Sub Protected Function GetBarCodeClientScript() As String Return String.Format("window.showSignaturePad($model, '{0}');", NameOf(Registration.Signature)) End Function Public ReadOnly Property SignatureAction() As SimpleAction Get Return signatureAction_Renamed End Get End Property End Class End Namespace

                                    Here we are calling the window.showSignaturePad function (registered at the step #3) and passing two parameters: the view's model and the image property name which will be used for storing a signature.

                                    Now you can run the application, create a new Registration record and execute the Action in the top right corner. A popup dialog will be shown, as demonstrated in the image below:

                                    The Clear button clears the signature pad contents. The Save button saves the signature to the Registration business object's Signature image property.

                                    You will find a project ready for testing in the attachment (

                                    Search keywords: capture, signature, sign, mobile, e-sign, echosign, document signing

                                • james baillie 03.03.2019

                                  Hey guys if any want the Version I battle with dont forget to the registration in the web config and add the module in mobileapplication code but its working thank to guys for all the help

                                • Dennis (DevExpress) 03.04.2019

                                  Thank you for sharing, James!

                                0 Solutions

                                Creation Date Importance Sort by