如何从JavaScript代码调用C#事件?

时间:2019-04-12 10:11:29

标签: c# xamarin.forms webview

在js中完成函数后,我需要在xamarin.forms中调用C#事件。请指导

   function readTextFile(file)
   {
       try
       {
           var blob = null;
           var rawFile = new XMLHttpRequest();
           rawFile.open(""GET"", file);
           rawFile.responseType = ""blob"";//force the HTTP response, response-type header to be blob
           rawFile.onload = function()
            {
                blob = rawFile.response;//xhr.response is now a blob object
                wavesurfer.loadBlob(blob);
                  wavesurfer2.loadBlob(blob);
            }
            rawFile.send();//I need to call C# event here.Please guide.
        }
        catch(err)
        {

        }
    }

1 个答案:

答案 0 :(得分:0)

解决方案:

您可以使用 CustomRenderer

实现它

1。以表格形式创建HybridWebView

public class HybridWebView : View
{
 Action<string> action;
 public static readonly BindableProperty UriProperty = BindableProperty.Create (
 propertyName: "Uri",
 returnType: typeof(string),
 declaringType: typeof(HybridWebView),
 defaultValue: default(string));

 public string Uri {
   get { return (string)GetValue (UriProperty); }
   set { SetValue (UriProperty, value); }
 }   

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

在contentPage.xaml

<ContentPage.Content>
    <local:HybridWebView x:Name="hybridWebView" Uri="xxx.html"
      HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>

后面的代码中

public MainPage ()
{
 ...
 hybridWebView.RegisterAction (data => DisplayAlert ("Alert", "JS action has been called", "OK")); //you can do something other as you want
}
  

在iOS项目中

[assembly: ExportRenderer (typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace xxx.iOS
{
  public class HybridWebViewRenderer : ViewRenderer<HybridWebView, WKWebView>, IWKScriptMessageHandler
  {
    const string JavaScriptFunction = "function invokeCSharpAction(data){window.webkit.messageHandlers.invokeAction.postMessage(data);}";
    WKUserContentController userController;

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

        if (Control == null) {
            userController = new WKUserContentController ();
            var script = new WKUserScript (new NSString (JavaScriptFunction), WKUserScriptInjectionTime.AtDocumentEnd, false);
            userController.AddUserScript (script);
            userController.AddScriptMessageHandler (this, "invokeAction");

            var config = new WKWebViewConfiguration { UserContentController = userController };
            var webView = new WKWebView (Frame, config);
            SetNativeControl (webView);
        }
        if (e.OldElement != null) {
            userController.RemoveAllUserScripts ();
            userController.RemoveScriptMessageHandler ("invokeAction");
            var hybridWebView = e.OldElement as HybridWebView;
            hybridWebView.Cleanup ();
        }
        if (e.NewElement != null) {
            string fileName = Path.Combine (NSBundle.MainBundle.BundlePath, string.Format ("Content/{0}", Element.Uri));
            Control.LoadRequest (new NSUrlRequest (new NSUrl (fileName, false)));
        }
    }

    public void DidReceiveScriptMessage (WKUserContentController userContentController, WKScriptMessage message)
    {
        Element.InvokeAction (message.Body.ToString ());
    }
  }
}

在Android项目中

[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace xxx.Droid
{
  public class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
    const string JavascriptFunction = "function invokeCSharpAction(data){jsBridge.invokeAction(data);}";
    Context _context;

    public HybridWebViewRenderer(Context context) : base(context)
    {
        _context = context;
    }

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

        if (Control == null)
        {
            var webView = new Android.Webkit.WebView(_context);
            webView.Settings.JavaScriptEnabled = true;
            webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
            SetNativeControl(webView);
        }
        if (e.OldElement != null)
        {
            Control.RemoveJavascriptInterface("jsBridge");
            var hybridWebView = e.OldElement as HybridWebView;
            hybridWebView.Cleanup();
        }
        if (e.NewElement != null)
        {
            Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
            Control.LoadUrl($"file:///android_asset/Content/{Element.Uri}");
        }
    }
  }
}

public class JavascriptWebViewClient : WebViewClient
{
  string _javascript;

  public JavascriptWebViewClient(string javascript)
  {
      _javascript = javascript;
  }

  public override void OnPageFinished(WebView view, string url)
  {
      base.OnPageFinished(view, url);
      view.EvaluateJavascript(_javascript, null);
 }
}
  

在您的HTML

function readTextFile(file)
{
   try
   {
       var blob = null;
       var rawFile = new XMLHttpRequest();
       rawFile.open(""GET"", file);
       rawFile.responseType = ""blob"";//force the HTTP response, response-type header to be blob
       rawFile.onload = function()
        {
            blob = rawFile.response;//xhr.response is now a blob object
            wavesurfer.loadBlob(blob);
              wavesurfer2.loadBlob(blob);
        }
        rawFile.send();

        invokeCSharpAction(data); //you can pass some params if you need

    }
    catch(err)
    {

    }
 }

有关更多详细信息,请参阅here