I have been trying to figure out how to invoke the custom renderer OnElementChanged for the next time when BindableProperty is changed.
In my case to keep it short for understanding purpose I need to refresh the webview url in android, uwp, ios renderer's.
First time initializing the value works but later when URL changes it doesn't invoke.
So alteast if there would have been a function in custom renderer class then we could have called and updated the native control.
Tried with android and uwp but have same issue. Once url loaded further changing it doesn't refresh the webview.
So for sample sake I have provided UWP renderer if it works here then similar changes can be done in android renderer. But not sure where exactly changes to be made to make it work.
XAML
<StackLayout>
<Entry Keyboard="Url" x:Name="txtUrl" Placeholder="Enter the URL" />
<Button x:Name="ButtonImage" Text="Search" Clicked="OnButtonClicked" />
<local:HybridWebView x:Name="webView" />
</StackLayout>
Xaml.cs
public partial class WebVieDemo : ContentPage
{
public WebVieDemo()
{
InitializeComponent();
webView.Uri = "https://www.101cookbooks.com/archives/blueberry-beet-pancakes-vegan-recipe.html";
}
private void OnButtonClicked(object sender, EventArgs e)
{
txtUrl.Text = "https://stackoverflow.com/questions/1531093/how-do-i-get-the-current-date-in-javascript";
webView.Uri = txtUrl.Text; // doesn't refresh the webview
}
}
HybridWebView.cs
public class HybridWebView : WebView
{
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 static readonly BindableProperty HtmlSourceProperty = BindableProperty.Create(
propertyName: "HtmlSource",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string HtmlSource
{
get { return (string)GetValue(HtmlSourceProperty); }
set { SetValue(HtmlSourceProperty, value); }
}
}
UWP Renderer
[assembly: ExportRenderer(typeof(HybridWebView), typeof(WindowsWebViewRenderer))]
namespace DemoApp.UWP
{
public class WindowsWebViewRenderer : ViewRenderer<HybridWebView, WebView>
{
HybridWebView hybridWebView = null;
protected override void OnElementChanged(ElementChangedEventArgs<HybridWebView> e)
{
base.OnElementChanged(e);
if (Control == null)
{
// Create the native control and use SetNativeControl
var webView = new WebView();
webView.LoadCompleted += WebView_LoadCompleted;
SetNativeControl(webView);
}
if (e.OldElement != null)
{
// Cleanup resources and remove event handlers for this element.
}
if (e.NewElement != null)
{
// Use the properties of this element to assign to the native control, which is assigned to the base.Control property
hybridWebView = e.NewElement;
if (hybridWebView.Uri != null)
Control.Source = new Uri(e.NewElement.Uri);
}
}
async private void WebView_LoadCompleted(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e)
{
hybridWebView.HtmlSource = await Control.InvokeScriptAsync("eval", new string[] { "document.documentElement.outerHTML;" });
}
}
}
In your custom renderer, you need to override OnElementPropertyChanged for this, not OnElementChanged, so something like:
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == HybridWebView.UriProperty.PropertyName)
{
if (Control.Uri != null)
Control.Source = new Uri(Control.Uri);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With