WPF WebBrowser - открывать ссылки в браузере по умолчанию

Я использую элемент управления WPF System.Windows.Controls.WebBrowser для отображения некоторого содержимого HTML, загруженного из службы. Иногда HTML-код содержит URL-адреса (элементы "a"), на которые следует нажимать.

По умолчанию при щелчке по такому URL-адресу он открывается в Internet Explorer. Вместо этого я хочу, чтобы они открывались в браузере по умолчанию.

Обратите внимание, я говорю конкретно о WPF WebBrowser. Для браузера WinForms существует множество решений, но они не работают для браузера WPF.

Наиболее распространенное «решение» - обработать событие Navigating, отменить его, а затем выполнить свои собственные действия с URL-адресом. Этот не работает, потому что событие Navigating не вызывается, когда я нажимаю ссылку в HTML.

Другое решение, которое я нашел, похоже, работает, но только иногда по какой-то странной причине: https://stackoverflow.com/a/9111151/573249

Теперь у меня есть следующий код, используя метод из приведенной выше ссылки:

private void WebBrowser_OnNavigating(object sender, NavigatingCancelEventArgs e)
{
    // Just for demonstration purposes
    // This is NOT CALLED when a link is clicked

    Debug.WriteLine("> Navigating called.");

    if (e.Uri == null)
    {
        Debug.WriteLine(">> URI was null.");
        return;
    }
    e.Cancel = true;
    Process.Start(e.Uri.AbsolutePath);
    Debug.WriteLine(">> Navigation cancelled and opened in default browser.");
}

private void WebBrowser_OnLoadCompleted(object sender, NavigationEventArgs e)
{
    Debug.WriteLine("> LoadCompleted called.");

    mshtml.HTMLDocument doc;
    doc = (mshtml.HTMLDocument) webBrowser.Document;
    mshtml.HTMLDocumentEvents2_Event iEvent;
    iEvent = (mshtml.HTMLDocumentEvents2_Event) doc;
    iEvent.onclick += new mshtml.HTMLDocumentEvents2_onclickEventHandler(ClickEventHandler);

    Debug.WriteLine("> LoadCompleted finished!");
    Debug.WriteLine("------");
}

private bool ClickEventHandler(mshtml.IHTMLEventObj e)
{
    // This finally opens the URL in the default browser
    // The method is called only 20% of the time.

    Debug.WriteLine(">> Click event handler called.");

    var a = (mshtml.HTMLAnchorElement) e.srcElement;
    Process.Start(a.href);
    return false;
}

Когда я нажимаю ссылку, кажется, что она работает примерно в 20% случаев. В этих случаях вызывается ClickEventHandler, и ссылка открывается в браузере по умолчанию. В остальных 80% случаев ClickEventHandler никогда не вызывается (и ссылка открывается в IE), даже если OnLoadCompleted завершается без исключений.

Кажется, что здесь нет шаблона, хотя, когда он однажды терпит неудачу, кажется, что он постоянно терпит неудачу в том же документе, пока я не перезагружу HTML. После повторной загрузки вероятность работы снова 20%.

В чем дело?


person Nick Thissen    schedule 28.01.2016    source источник
comment
Я использую WPF WebBrowser и обрабатываю событие Navigation, и это работает для меня. Событие вызывается, когда я нажимаю ссылку в HTML.   -  person Tomas Kosar    schedule 17.08.2017


Ответы (1)


Привет, у меня была точно такая же проблема. Событие OnMouseDown запускалось просто иногда. И я не мог этого понять. Я просто сдался и вместо этого использовал WinForm WebBrowser. Тогда вам не нужна ссылка на MSHTML, но вам нужна ссылка на System.Windows.Forms и System.Windows.Interactivity.

XAML

xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"

<WindowsFormsHost>
  <wf:WebBrowser x:Name="WbThumbs"/>
</WindowsFormsHost>

C#

public WMain() {
  System.Windows.Forms.Application.EnableVisualStyles();
  InitializeComponent();

  WbThumbs.DocumentCompleted += WbThumbsOnDocumentCompleted;
  WbThumbs.Navigate("www.blabla.com");
}

private void WbThumbsOnDocumentCompleted(object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e) {
  if (WbThumbs.Document == null) return;
  WbThumbs.Document.Click += WbThumbs_Click;
}

private void WbThumbs_Click(object sender, System.Windows.Forms.HtmlElementEventArgs e) {
  var doc = WbThumbs.Document;
  var src = doc?.GetElementFromPoint(e.ClientMousePosition);
  if (src == null) return;
  //...
}
person MartinHoly    schedule 06.02.2016