WPF WebBrowser的LoadCompleted事件

3

WPF WebBrowser的LoadCompleted事件何时触发?该事件是否等待aspx页面中的任何ajax调用完成。

我有一个WPF应用程序,在其中放置了一个WebBrowser控件,并使用Navigate方法加载了一个网页。即使某些ajax调用未初始化/等待,LoadCompleted事件也会触发。

请建议在加载网页100%(包括所有ajax调用)后触发的任何事件。


无法观察脚本代码的执行。 - Hans Passant
3个回答

1

我已经解决了这个问题。

您需要一些第三方程序集:

  1. FiddlerCore:作为嵌入在您的应用程序中的http代理
  2. Awesomium.net:一个与chromium引擎配合工作的WebBrowser控件。我选择了这个引擎,因为它允许为应用程序指定代理服务器。

想法很简单,就是创建一个内存中的代理服务器,并将您的Web浏览器控件重定向到该代理。

然后,FiddlerCore发布一些事件,您可以在其中分析请求/响应,特别是正文。

由于它充当代理,所有通信,包括Ajax调用、Flash调用等,都通过代理路由。

如果有帮助的话,这是一个帮助我原型化这种行为的小代码:

App.cs:

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        BootStrap();
        base.OnStartup(e);
    }

    private void BootStrap()
    {
        SetupInternalProxy();
        SetupBrowser();
    }

    private static void SetupBrowser()
    {
        // We may be a new window in the same process.
        if (!WebCore.IsRunning)
        {
            // Setup WebCore with plugins enabled.
            WebCoreConfig config = new WebCoreConfig
            {
                ProxyServer = "http://127.0.0.1:" + FiddlerApplication.oProxy.ListenPort.ToString(),
                EnablePlugins = true,
                SaveCacheAndCookies = true
            };
            WebCore.Initialize(config);
        }
        else
        {
            throw new InvalidOperationException("WebCore should be already running");
        }
    }

    private void SetupInternalProxy()
    {
        FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete;
        FiddlerApplication.Log.OnLogString += (o, s) => Debug.WriteLine(s);

        FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
        //this line is important as it will avoid changing the proxy for the whole system.
        oFCSF = (oFCSF & ~FiddlerCoreStartupFlags.RegisterAsSystemProxy);

        FiddlerApplication.Startup(
            0,
            oFCSF
            );
    }

    private void FiddlerApplication_AfterSessionComplete(Session oSession)
    {
        Debug.WriteLine(oSession.GetResponseBodyAsString());
    }
}

MainWindow.xaml:

<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1" 
        xmlns:Custom="http://schemas.awesomium.com/winfx" 
        x:Class="WpfApplication1.MainWindow"
        Title="MainWindow" Height="350" Width="525" Loaded="MainWindow_Loaded">
    <Grid>

        <Custom:WebControl Name="browser"/>

    </Grid>
</Window>

最后,MainWindow.xaml.cs :

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        browser.LoadURL("http://google.fr");
    }
}

您需要在此应用程序中添加一些管道,以便将请求从应用程序路由和分析到业务类,但这超出了本问题的范围。


0

LoadComplete事件的文档说明:

当正在导航到的文档下载完成时发生。

这意味着当URL下载完成后,它将触发。它并不意味着任何引用的项目(图像、脚本等)都会触发该事件。

此外,除非您钩入JavaScript引擎本身(我不知道是否可以这样做),以便在回调到Web服务器时得到通知,否则不能保证它是Ajax调用;没有关于调用的标准,通常您使用的各种库的Ajax调用都是不同的。

例如,jQuery使用ajax()方法,而scriptalicious在内部包装调用,并且不提供直接进行Ajax调用的方法。

或者,您可以直接使用XMLHttpRequest对象进行调用。

即使您可以将其缩小到使用XMLHttpRequest的调用,您也不会知道哪些调用是用于Ajax的;可以调用的URL不指示它们是否为Ajax,返回的内容类型(纯文本、XML、JSON)也不指示。


-2

如果你理解了.NET Web模型下面的页面生命周期,你就能看到更大的画面。

  1. Page_PreInit
  2. 列表项
  3. Page_Init
  4. Page_InitComplete
  5. Page_PreLoad
  6. Page_Load
  7. 控件事件
  8. Page_LoadComplete
  9. Page_PreRender
  10. SaveViewState
  11. Page_Render
  12. Page_Unload

5
这些是服务器端ASP.Net事件,与此问题无关。 - O'Rooney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接