0

我正在开发一个跨平台的 xamarin 表单应用程序。我创建了一个便携式跨平台应用程序,我试图在其中打开 webview 中的本地 HTML 页面。为了从 Angularjs 调用 C# 函数,我实现了混合 Web 视图概念。

我的 Angularjs 函数

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

在我的通用 Windows 项目中

 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);
    }
}

我的 commInterface 类

 [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);
        }
    }
}

就像在 Android 项目中一样,我使用 CommInterface 类与 Portable 库中的数据库类进行通信。但是在我的通用 Windows 项目中,我无法与 Csharp 函数通信以运行 CSharp CRUD 函数。如何从脚本调用 CSharp 函数?

4

1 回答 1

1

我无法与 Csharp 函数通信以运行 CSharp CRUD 函数。如何从脚本调用 CSharp 函数?

JS您在 webView 导航完成后注入了脚本。换句话说,在范围内await Control.InvokeScriptAsync("eval", new[] { JavaScriptFunction });声明了。JS

Web 视图内容中的脚本可以使用带有字符串参数的window.external.notify将信息发送回您的应用程序。要接收这些消息,请处理该ScriptNotify事件。

因此,当您像以下代码一样执行范围内时,ScriptNotify将触发该事件。JavaScriptFunctionJS

<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);
    }
}

我发现你已经通过执行处理了ScriptNotify事件Element.InvokeAction(e.Value);所以我推断你声明了InvokeAction混合 web 视图。

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);
}

然后您可以在回调函数中处理 CSharp CRUD 函数,如下面的代码。

smbridwebview.RegisterAction(data => {
// process CSharp CRUD functions 
});
于 2017-03-20T06:28:51.070 回答