【问题标题】:Calling C# function from AngularJs script in Xamarin Forms PCL Universal Windows Application在 Xamarin Forms PCL 通用 Windows 应用程序中从 AngularJs 脚本调用 C# 函数
【发布时间】:2017-08-08 22:25:25
【问题描述】:

我正在开发一个跨平台的 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 函数?

【问题讨论】:

    标签: xamarin xamarin.forms portable-class-library hybrid xamarin.uwp


    【解决方案1】:

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

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

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

    所以当您在JS 范围内执行JavaScriptFunction 时会触发ScriptNotify 事件,如下面的代码。

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

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

    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-04-08
      • 1970-01-01
      • 2019-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2017-04-27
      • 2019-11-12
      相关资源
      最近更新 更多