Reputation: 705
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?
Upvotes: 0
Views: 1152
Reputation: 32775
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
});
Upvotes: 1