diff options
Diffstat (limited to 'Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs')
-rw-r--r-- | Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs new file mode 100644 index 00000000..8074f3f1 --- /dev/null +++ b/Xamarin.Forms.Platform.WinRT/WebViewRenderer.cs @@ -0,0 +1,174 @@ +using System; +using System.ComponentModel; +using Windows.UI.Core; +using Windows.UI.Xaml.Controls; + +#if WINDOWS_UWP + +namespace Xamarin.Forms.Platform.UWP +#else + +namespace Xamarin.Forms.Platform.WinRT +#endif +{ + public class WebViewRenderer : ViewRenderer<WebView, Windows.UI.Xaml.Controls.WebView>, IWebViewRenderer + { + WebNavigationEvent _eventState; + bool _updating; + + public void LoadHtml(string html, string baseUrl) + { + /* + * FIXME: If baseUrl is a file URL, set the Base property to its path. + * Otherwise, it doesn't seem as if WebBrowser can handle it. + */ + Control.NavigateToString(html); + } + + public void LoadUrl(string url) + { + Control.Source = new Uri(url); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (Control != null) + { + Control.NavigationStarting -= OnNavigationStarted; + Control.NavigationCompleted -= OnNavigationCompleted; + Control.NavigationFailed -= OnNavigationFailed; + } + } + + base.Dispose(disposing); + } + + protected override void OnElementChanged(ElementChangedEventArgs<WebView> e) + { + base.OnElementChanged(e); + + if (e.OldElement != null) + { + e.OldElement.EvalRequested -= OnEvalRequested; + e.OldElement.GoBackRequested -= OnGoBackRequested; + e.OldElement.GoForwardRequested -= OnGoForwardRequested; + } + + if (e.NewElement != null) + { + if (Control == null) + { + var webView = new Windows.UI.Xaml.Controls.WebView(); + webView.NavigationStarting += OnNavigationStarted; + webView.NavigationCompleted += OnNavigationCompleted; + webView.NavigationFailed += OnNavigationFailed; + SetNativeControl(webView); + } + + e.NewElement.EvalRequested += OnEvalRequested; + e.NewElement.GoForwardRequested += OnGoForwardRequested; + e.NewElement.GoBackRequested += OnGoBackRequested; + + Load(); + } + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + if (e.PropertyName == WebView.SourceProperty.PropertyName) + { + if (!_updating) + Load(); + } + } + + void Load() + { + if (Element.Source != null) + Element.Source.Load(this); + + UpdateCanGoBackForward(); + } + + async void OnEvalRequested(object sender, EventArg<string> eventArg) + { + await Control.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => Control.InvokeScript("eval", new[] { eventArg.Data })); + } + + void OnGoBackRequested(object sender, EventArgs eventArgs) + { + if (Control.CanGoBack) + { + _eventState = WebNavigationEvent.Back; + Control.GoBack(); + } + + UpdateCanGoBackForward(); + } + + void OnGoForwardRequested(object sender, EventArgs eventArgs) + { + if (Control.CanGoForward) + { + _eventState = WebNavigationEvent.Forward; + Control.GoForward(); + } + + UpdateCanGoBackForward(); + } + + void OnNavigationCompleted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationCompletedEventArgs e) + { + if (e.Uri != null) + SendNavigated(new UrlWebViewSource { Url = e.Uri.AbsoluteUri }, _eventState, WebNavigationResult.Success); + + UpdateCanGoBackForward(); + } + + void OnNavigationFailed(object sender, WebViewNavigationFailedEventArgs e) + { + if (e.Uri != null) + SendNavigated(new UrlWebViewSource { Url = e.Uri.AbsoluteUri }, _eventState, WebNavigationResult.Failure); + } + + void OnNavigationStarted(Windows.UI.Xaml.Controls.WebView sender, WebViewNavigationStartingEventArgs e) + { + Uri uri = e.Uri; + + if (uri != null) + { + var args = new WebNavigatingEventArgs(_eventState, new UrlWebViewSource { Url = uri.AbsoluteUri }, uri.AbsoluteUri); + + Element.SendNavigating(args); + e.Cancel = args.Cancel; + + // reset in this case because this is the last event we will get + if (args.Cancel) + _eventState = WebNavigationEvent.NewPage; + } + } + + void SendNavigated(UrlWebViewSource source, WebNavigationEvent evnt, WebNavigationResult result) + { + _updating = true; + ((IElementController)Element).SetValueFromRenderer(WebView.SourceProperty, source); + _updating = false; + + Element.SendNavigated(new WebNavigatedEventArgs(evnt, source, source.Url, result)); + + UpdateCanGoBackForward(); + _eventState = WebNavigationEvent.NewPage; + } + + // Nasty hack because we cant bind this because OneWayToSource isn't a thing in WP8, yay + void UpdateCanGoBackForward() + { + Element.CanGoBack = Control.CanGoBack; + Element.CanGoForward = Control.CanGoForward; + } + } +}
\ No newline at end of file |