WPF webbrowser's LoadCompleted event
When will the WPF webbrowser's LoadCompleted event fires? Is 开发者_如何学JAVAthis event waits for any ajax calls to complete in the aspx page.
i have a wpf app in which a webbrowser control placed on a window form and a webpage loaded using Navigate method. The LoadCompleted event fires even when some ajax calls not initialized/waiting.
Please suggest any event which fires after loading the webpage 100% including all ajax calls.
I have been able to solve such issue.
You will need some 3rd party assemblies :
- FiddlerCore: will act as a http proxy, embedded in your application
- Awesomium.net: a WebBrowser control, that works with the chromium engine. I choose this engine, because it allows to specify a proxy server just for the application.
The idea, as you guess, is to create an in-memory proxy server, and redirect your web browser control to this proxy.
Then, FiddlerCore publishes some events where you can analyse the request/response, especially the body.
As it acts a proxy, all communications, including Ajax calls, Flash calls, etc, are routed by the proxy.
If it can help, a small code that help me to prototype this behavior:
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>
And finally, MainWindow.xaml.cs :
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
browser.LoadURL("http://google.fr");
}
}
You will have to add some plumbing to this application, in order to route and analyse the requestion from the app to the business class, but that's beyond the scope of this question.
The documentation for the LoadComplete
event states:
Occurs when the document being navigated to has finished downloading.
This means that when the url is done downloading it will fire. It does *not mean that any of the referenced items will trigger the event (images, scripts, etc).
Additionally, unless you hook into the JavaScript engine itself (which I'm not aware if you can do) to be notified when a call is made back to the web server, it can't be guaranteed that it's an Ajax call; there's no standard around the calls and usually the calls for Ajax are different across the various libraries that you use.
For example jQuery uses the ajax()
method, while scriptalicious wraps calls internally and doesn't give you a way to make Ajax calls outright.
Or, you can make calls using the XMLHttpRequest
object directly.
Even if you could narrow it down to calls using XMLHttpRequest
, you wouldn't know which calls are for Ajax; the URLs that can be called don't indicate whether they are Ajax or not, nor does the content type returned (plain text, XML, JSON).
If you understand the below page life cycle of .NET web model, you will get the bigger picture.
- Page_PreInit
- List item
- Page_Init
- Page_InitComplete
- Page_PreLoad
- Page_Load
- Control Events
- Page_LoadComplete
- Page_PreRender
- SaveViewState
- Page_Render
- Page_Unload
精彩评论