我有一个Xamarin.Forms应用程序,它通过Uno Platform投影到WASM。单击或点击后,我需要打开一个Web链接。我用以下方法解决它:
try // Uwp & iOS & Android
{
await Browser.OpenAsync(new Uri("http://localhost"), BrowserLaunchMode.SystemPreferred); // Open url in-app browser for iOS & Android- native in UWP
}
catch (NotImplementedInReferenceAssemblyException ex) //Wasm falls here because lack of Xamarin.Essentials.
{
await DisplayAlert("Hata", "Not supported on WASM", "Anladım"); // Show the info about exception.
}
对于Xamarin。 Android和iOS,以及UWP(Windows)。但是,Xamarin.Essentials尚不能在WASM上运行。因此,我需要调用Javascript并运行以下代码:
function openPage(x) {
window.open(x);
}
我尝试将UNO.Foundation用于
WebAssemblyRuntime.InvokeJS("(function(){location.href=\"https://www.wikipedia.com/\";})();");
但是,它会干扰UWP UI类并破坏了我的项目。如何不使用UNO.Foundation类从Xamarin.Forms页面C#后端调用Javascript?谢谢。
您可以使用混合Web视图,然后注入JavaScript代码来检测对此Web视图的每次点击https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/hybridwebview
我通过Customizing via WebView解决了它:
[尝试创建将WebView扩展到允许从JavaScript调用C#代码。
WebView Renderer的过程:
创建HybridWebView自定义控件。从以下位置使用HybridWebViewXamarin.Forms。在以下位置为HybridWebView创建自定义渲染器每个平台。当用户单击HTML按钮时,JavaScript函数将调用C#Action。
1。创建HybridWebView
public class HybridWebView : WebView
{
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);
}
}
2。使用HybridWebView
<ContentPage
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
x:Class="CustomRenderer.HybridWebViewPage"
Padding="0,40,0,0">
<local:HybridWebView x:Name="hybridWebView"
Uri="index.html" />
</ContentPage>
3。在UWP上创建自定义渲染器
[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace CustomRenderer.UWP
{
public class HybridWebViewRenderer : WebViewRenderer
{
const string JavaScriptFunction = "function invokeCSharpAction(data){window.external.notify(data);}";
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
Control.NavigationCompleted -= OnWebViewNavigationCompleted;
Control.ScriptNotify -= OnWebViewScriptNotify;
}
if (e.NewElement != null)
{
Control.NavigationCompleted += OnWebViewNavigationCompleted;
Control.ScriptNotify += OnWebViewScriptNotify;
Control.Source = new Uri($"ms-appx-web:///Content//{((HybridWebView)Element).Uri}");
}
}
async void OnWebViewNavigationCompleted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationCompletedEventArgs args)
{
if (args.IsSuccess)
{
// Inject JS script
await Control.InvokeScriptAsync("eval", new[] { JavaScriptFunction });
}
}
void OnWebViewScriptNotify(object sender, NotifyEventArgs e)
{
((HybridWebView)Element).InvokeAction(e.Value);
}
}
}
最后,从代码中调用函数:
hybridWebView.RegisterAction(data => Browser.OpenAsync(data, BrowserLaunchMode.SystemPreferred));
hybridWebView.InvokeAction("http://localhost");