-
Notifications
You must be signed in to change notification settings - Fork 3
Navigation
The Navigating
event allows you to cancel navigation using the following syntax.
async void OnNavigating(object sender, SuperWebNavigatingEventArgs e)
{
if (e.CanCancel)
{
var token = e.GetDeferral();
bool canBrowse = await EvaluateUrlAsync(e.Url);
if (!canBrowse)
{
e.Cancel();
}
token.Complete();
}
}
You can cancel navigation synchronously or asynchronously.
To start the process, request a DeferralToken
:
async void OnNavigating(object sender, SuperWebNavigatingEventArgs e)
{
if (e.CanCancel)
{
var token = e.GetDeferral();
}
}
Once you have requested this token, you must return it otherwise it will block the SuperWebView
from performing any more actions.
If you do not acquire this token, navigation will be automatically granted.
If you wish to cancel the navigation, call the Cancel()
method on the SuperWebNavigatingEventArgs
:
async void OnNavigating(object sender, SuperWebNavigatingEventArgs e)
{
if (e.CanCancel)
{
var token = e.GetDeferral();
e.Cancel();
}
}
Once you have decided whether to cancel navigation, hand the token back by calling the Complete()
method:
async void OnNavigating(object sender, SuperWebNavigatingEventArgs e)
{
if (e.CanCancel)
{
var token = e.GetDeferral();
e.Cancel();
token.Complete();
}
}
It is advised but not necessary to check if cancellation can occur before acquiring a deferral token. If e.CanCancel
is false, a fake deferral token will be returned and it will have no impact on the navigation event.
This feature is the reason I forked the original control. There are numerous issues on Xamarin Forms relating to cancelling navigation using async await
(#13834, #12720). The issue is that with the current implementation of the renderers, when the Navigating
event is fired, you have a small window to change the Cancel
value to true/false before the renderer evaluates whether the control can browse to a site. This means that when using a long running task to decide whether the site can be accessed, the page will be loaded before the task returns. Here are the references in the source code: see iOS, Android).
I originally added a new property to NavigatingWebSourceArgs
that added a task that could be awaited within a renderer to achieve the desired outcome. I raised a PR (#12756) with the Xamarin team and they suggested that I use the DeferalToken
concept from Shell
to essentially block the UI thread from running until my background task completes. I have since completed that implementation and raised another PR (#14137), but unfortunately due to Xamarin Forms being close to EOL and the team busy with .NET MAUI, I doubt the change will be implemented at all. Due to having a hard requirement for this functionality in an app I am developing, I took matters into my own hands and went nuclear.