2

My app has a WebView for displaying some contact information. It has a link to a website that I want to load externally using Device.OpenUri(). I'm using FreshMvvm and I want to intercept the Navigating event from the WebView in the ViewModel and cancel the default action which would load the external page into the WebView.

I've tried using the Corcav.Behaviors plugin which does call my ViewModel command:

        <WebView
            HorizontalOptions="Fill" 
            VerticalOptions="FillAndExpand" 
            Source="{Binding WebViewSource}">
              <b:Interaction.Behaviors>
                <b:BehaviorCollection>
                    <b:EventToCommand
                        EventName="Navigating"
                        Command="{Binding NavigatingCommand}"
                        CommandParameter="{Binding}"/> <!-- what goes here -->
                </b:BehaviorCollection>
              </b:Interaction.Behaviors>
        </WebView>

But I'm not sure what the CommandParameter should be - I need the URI of the link that was tapped, and I don't know how to then prevent the default behaviour from occurring.

Is this the best approach or should I be looking at an alternative?

David Clarke
  • 12,888
  • 9
  • 86
  • 116
  • No need to specify the CommandParameter, NavigatingCommand should be of type DelegateCommand, the tappedItem is the item property of the argument. – Rauland Jan 03 '17 at 12:29
  • @rauland when I use that approach, i.e. leaving out the CommandParameter, I get nothing passed as the parameter - even when specifying `object` as the parameter type. – David Clarke Mar 27 '17 at 21:42

2 Answers2

3

Having revisited this recently for another project I stumbled across the answer. The updated XAML is:

<WebView
    x:Name="webView"
    HorizontalOptions="Fill" 
    VerticalOptions="FillAndExpand" 
    Source="{Binding WebViewSource}">
    <behaviors:Interaction.Behaviors>
        <behaviors:BehaviorCollection>
            <behaviors:EventToCommand
                EventName="Navigating"
                Command="{Binding NavigatingCommand}"
                PassEventArgument="True" />
        </behaviors:BehaviorCollection>
    </behaviors:Interaction.Behaviors>
</WebView>

The code in the ViewModel, that matches the tapped url against a list of valid options before opening the link in the device's browser, is:

public Command<WebNavigatingEventArgs> NavigatingCommand
{
    get
    {
        return navigatingCommand ?? (navigatingCommand = new Command<WebNavigatingEventArgs>(
            (param) =>
            {
                if (param != null && -1 < Array.IndexOf(_uris, param.Url))
                {
                    Device.OpenUri(new Uri(param.Url));
                    param.Cancel = true;
                }
            },
            (param) => true
            ));
    }
}
Community
  • 1
  • 1
David Clarke
  • 12,888
  • 9
  • 86
  • 116
0

You can´t navigate with a WebView, you must use a custom render (hybridwebview). Here is an explanation:

https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/hybridwebview/

  • 1
    Maybe you've misinterpreted what I'm trying to achieve. I want to intercept the `Navigating` event that is triggered when tapping on a link in a WebView and then open the associated URL in an external browser. I'm not trying to use the link to navigate within the app. – David Clarke Mar 28 '17 at 20:41