Xamarin.Mac WebView won’t launch links set to open in a new tab or window.

By default when using a WebView in a MonoMac/Xamarin.Mac project, links that are set to open in a new window will not launch at all. To change this behavior and have all links open in the same WebView, you will need to subclass WebPolicyDelegate and implement one method. There are other methods of the WebPolicyDelegate class that you may want to implement as well, so I will leave them in but commented out. Code below the fold.

The MyWebPolicyDelegate class:

public class MyWebPolicyDelegate : WebPolicyDelegate
{
    public MyWebPolicyDelegate() : base()
    {
    }

//  public override void DecidePolicyForMimeType(WebView webView, 
//                                                string mimeType, 
//                       MonoMac.Foundation.NSUrlRequest request, 
//                                              WebFrame frame, 
//                           MonoMac.Foundation.NSObject decisionToken)
//  {
//  }

    public override void DecidePolicyForNewWindow(WebView webView, 
                          MonoMac.Foundation.NSDictionary actionInformation, 
                          MonoMac.Foundation.NSUrlRequest request, 
                                                   string newFrameName, 
                              MonoMac.Foundation.NSObject decisionToken)
    {
        webView.MainFrame.LoadRequest(request);
    }

//  public override void DecidePolicyForNavigation(WebView webView, 
//                         MonoMac.Foundation.NSDictionary actionInformation, 
//                         MonoMac.Foundation.NSUrlRequest request, 
//                                                WebFrame frame, 
//                             MonoMac.Foundation.NSObject decisionToken)
//  {
//      WebView.DecideUse(decisionToken); 
//  }
//
//  public override void UnableToImplementPolicy(WebView webView, 
//                            MonoMac.Foundation.NSError error, 
//                                              WebFrame frame)
//  {
//  }
}

The DecidePolicyForNewWindow() method is doing just that, deciding what to do when a link that is meant to be launched in a new window is clicked. In this case we are simply loading the request into the same WebView. The DecidePolicyForNavigation() is called whenever any link in the WebView is clicked, but if not implemented links that are coded to open in the same browser window will open in the same WebView. Now that we have the WebPolicyDelegate subclass, we have to tell the WebView about it. In this case my WebView was set in the XIB file with an outlet called webView to access it.

In your MainWindowController class:

public override void AwakeFromNib()
{
    base.AwakeFromNib();
    webView.MainFrame.LoadRequest(new NSUrlRequest
                               (new NSUrl( "http://blog.onobytes.com")));
    webView.PolicyDelegate = new MyWebPolicyDelegate();
}

And that’s about it!

Update: I realize now that these methods of the WebPolicyDelegate are mapped to event handlers on a WebView, so you can use:

web.DecidePolicyForNavigation += (object sender, WebNavigationPolicyEventArgs e) => {
    WebView.DecideUse(e.DecisionToken);
};

web.DecidePolicyForNewWindow += (object sender, WebNewWindowPolicyEventArgs e) => {
    web.MainFrame.LoadRequest(e.Request);
};

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *