0

I am developing a cross platform xamarin forms application. I have created a Portable Cross-Platform App, in which I am trying to open local HTML pages in webview. For calling C# function from Angularjs, I have implemented hybrid web view concepts.

My Angularjs Function

 $scope.SyncServerJobs = function () {
    //$scope.loadActList();
   window.CommInterface.syncServerJobs("");
}

In My Universal Windows Project

 public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Windows.UI.Xaml.Controls.WebView>
{
    public CommInterface communicator = new CommInterface();

    const string JavaScriptFunction = "function invokeCSharpAction(data){window.external.notify(data);}";
    const string SyncServerJobs = "function syncServerJobs(data){window.external.notify(data);}";

    protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
    {
        base.OnElementChanged(e);

        if (Control == null)
        {
            var webView = new WebView();
            webView.Settings.IsJavaScriptEnabled = true;
            SetNativeControl(webView);
        }
        if (e.OldElement != null)
        {
            Control.NavigationStarting -= OnWebViewNavigationStarted;
            Control.NavigationCompleted -= OnWebViewNavigationCompleted;
            Control.ScriptNotify -= OnWebViewScriptNotify;
        }
        if (e.NewElement != null)
        {
            Control.NavigationStarting += OnWebViewNavigationStarted;
            Control.NavigationCompleted += OnWebViewNavigationCompleted;
            Control.ScriptNotify += OnWebViewScriptNotify;
            Control.Source = new Uri(string.Format("ms-appx-web:///Content//{0}", Element.Uri));
        }
    }

    private void OnWebViewNavigationStarted(WebView sender, WebViewNavigationStartingEventArgs args)
    {
        if (Control != null && Element != null)
        {
            communicator = new CommInterface();
            Control.AddWebAllowedObject("CommInterface", communicator);
        }
    }

    async void OnWebViewNavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
    {
        if (args.IsSuccess)
        {
            // Inject JS script
            await Control.InvokeScriptAsync("eval", new[] { JavaScriptFunction });
            await Control.InvokeScriptAsync("eval", new[] { SyncServerJobs });
        }
    }

    void OnWebViewScriptNotify(object sender, NotifyEventArgs e)
    {
        Element.InvokeAction(e.Value);
    }
}

My commInterface class

 [AllowForWeb]
public sealed class CommInterface
{
    readonly WeakReference<HybridWebViewRenderer> hybridWebViewRenderer;

    public CommInterface()
    {

    }

    public void syncServerJobs(string data)
    {
        HybridWebViewRenderer hybridRenderer;
        if (hybridWebViewRenderer != null && hybridWebViewRenderer.TryGetTarget(out hybridRenderer))
        {
            hybridRenderer.Element.SyncServerJobs(data);
        }
    }
}

As like in Android project I am using CommInterface class to communicate with database class in Portable library. But in my Universal Windows project, I am not able to communicate with Csharp functions to run CSharp CRUD functions. How can I call the CSharp function from script?

1 Answer 1

1

I am not able to communicate with Csharp functions to run CSharp CRUD functions. How can I call the CSharp function from script?

You have injected JS script after webView navigation Completed. In another words the await Control.InvokeScriptAsync("eval", new[] { JavaScriptFunction }); was declared in JS scope.

Scripts in the web view content can use window.external.notify with a string parameter to send information back to your app. To receive these messages, handle the ScriptNotify event.

So The ScriptNotify event would be triggered when you executed the JavaScriptFunction in JS scope like the follwing code.

<button type="button" onclick="javascript:invokeCSCode($('#name').val());">Invoke C# Code</button>
<br/>
<p id="result">Result:</p>
<script type="text/javascript">
function log(str)
{
    $('#result').text($('#result').text() + " " + str);
}

function invokeCSCode(data) {
    try {
        log("Sending Data:" + data);
        invokeCSharpAction(data);    
    }
    catch (err){
        log(err);
    }
}

I found you have handled the ScriptNotify event by excuted Element.InvokeAction(e.Value); So I infer that you declared the InvokeAction for hybrid web view.

public void RegisterAction(Action<string> callback)
{
    action = callback;
}

public void Cleanup()
{
    action = null;
}

public void InvokeAction(string data)
{
    if (action == null || data == null)
    {
        return;
    }
    action.Invoke(data);
}

And then you could process CSharp CRUD functions in the callback function like the following code.

smbridwebview.RegisterAction(data => {
// process CSharp CRUD functions 
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.