C# HTML - 我如何知道何时加载了所有框架?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/672731/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML - How do I know when all frames are loaded?
提问by Yuval Peled
I'm using .NET WebBrowser control. How do I know when a web page is fully loaded?
我正在使用 .NET WebBrowser 控件。我如何知道网页何时完全加载?
I want to know when the browser is not fetching any more data. (The moment when IE writes 'Done' in its status bar...).
我想知道浏览器何时不再获取任何数据。(IE 在其状态栏中写入“完成”的那一刻......)。
Notes:
笔记:
- The DocumentComplete/NavigateComplete events might occur multiple times for a web site containing multiple frames.
- The browser ready state doesn't solve the problem either.
- I have tried checking the number of frames in the frame collection and then count the number of times I get DocumentComplete event but this doesn't work either.
- this.WebBrowser.IsBusy doesn't work either. It is always 'false' when checking it in the Document Complete handler.
- 对于包含多个框架的网站,DocumentComplete/NavigateComplete 事件可能会发生多次。
- 浏览器就绪状态也不能解决问题。
- 我曾尝试检查帧集合中的帧数,然后计算获得 DocumentComplete 事件的次数,但这也不起作用。
- this.WebBrowser.IsBusy 也不起作用。在 Document Complete 处理程序中检查它时它总是“false”。
采纳答案by Yuval Peled
Here's what finally worked for me:
以下是最终对我有用的内容:
public bool WebPageLoaded
{
get
{
if (this.WebBrowser.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
return false;
if (this.HtmlDomDocument == null)
return false;
// iterate over all the Html elements. Find all frame elements and check their ready state
foreach (IHTMLDOMNode node in this.HtmlDomDocument.all)
{
IHTMLFrameBase2 frame = node as IHTMLFrameBase2;
if (frame != null)
{
if (!frame.readyState.Equals("complete", StringComparison.OrdinalIgnoreCase))
return false;
}
}
Debug.Print(this.Name + " - I think it's loaded");
return true;
}
}
On each document complete event I run over all the html element and check all frames available (I know it can be optimized). For each frame I check its ready state. It's pretty reliable but just like jeffamaphone said I have already seen sites that triggered some internal refreshes. But the above code satisfies my needs.
在每个文档完成事件上,我遍历所有 html 元素并检查所有可用的框架(我知道它可以优化)。对于每一帧,我检查它的就绪状态。它非常可靠,但就像 jeffamaphone 所说的那样,我已经看到了触发一些内部刷新的网站。但是上面的代码满足了我的需求。
Edit: every frame can contain frames within it so I think this code should be updated to recursively check the state of every frame.
编辑:每个帧都可以包含其中的帧,所以我认为应该更新此代码以递归检查每个帧的状态。
回答by Anand Shah
Have you tried WebBrowser.IsBusy
property?
你试过WebBrowser.IsBusy
财产吗?
回答by mbeckish
How about using javascript in each frame to set a flag when the frame is complete, and then have C# look at the flags?
当框架完成时,在每个框架中使用 javascript 设置一个标志,然后让 C# 查看标志怎么样?
回答by roryf
I don't have an alternative for you, but I wonder if the IsBusy
property being tru
e during the Document Complete handler is because the handler is still running and therefore the WebBrowser
control is technically still 'busy'.
我没有其他选择,但我想知道在 Document Complete 处理程序期间IsBusy
属性为tru
e 是否是因为处理程序仍在运行,因此WebBrowser
控件在技术上仍然“忙碌”。
The simplest solution would be to have a loop that executes every 100 ms or so until the IsBusy
flag is reset (with a max execution time in case of errors). That of course assumes that IsBusy
will not be set to false
at any point during page loading.
最简单的解决方案是让循环每 100 毫秒左右执行一次,直到IsBusy
标志被重置(在出现错误的情况下具有最大执行时间)。这当然假设在页面加载期间IsBusy
不会false
在任何时候设置为。
If the Document Complete handler executes on another thread, you could use a lock to send your main thread to sleep and wake it up from the Document Complete thread. Then check the IsBusy
flag, re-locking the main thread is its still true
.
如果文档完成处理程序在另一个线程上执行,您可以使用锁将主线程发送到休眠状态并从文档完成线程唤醒它。然后检查IsBusy
标志,重新锁定主线程是它的 still true
。
回答by paulgreg
I'm not sure it'll work but try to add a JavaScript "onload" event on your frameset like that :
我不确定它是否会起作用,但尝试在您的框架集上添加一个 JavaScript“onload”事件,如下所示:
function everythingIsLoaded() { alert("everything is loaded"); }
var frameset = document.getElementById("idOfYourFrameset");
if (frameset.addEventListener)
frameset.addEventListener('load',everythingIsLoaded,false);
else
frameset.attachEvent('onload',everythingIsLoaded);
回答by kgiannakakis
Can you use jQuery? Then you could easily bind frame ready events on the target frames. See thisanswer for directions. This blog postalso has a discussion about it. Finally there is a plug-inthat you could use.
你会使用 jQuery 吗?然后您可以轻松地在目标帧上绑定帧就绪事件。有关说明,请参阅此答案。这篇博文也有关于它的讨论。最后,您可以使用一个插件。
The idea is that you count the number of frames in the web page using:
这个想法是您使用以下方法计算网页中的帧数:
$("iframe").size()
and then you count how many times the iframe ready event has been fired.
然后计算 iframe 就绪事件被触发的次数。
回答by i_am_jorf
You will get a BeforeNavigate and DocumentComplete event for the outer web page, as well as each frame. You know you're done when you get the DocumentComplete event for the outer webpage. You should be able to use the managed equivilent of IWebBrowser2::TopLevelContainer()to determine this.
您将获得外部网页以及每个框架的 BeforeNavigate 和 DocumentComplete 事件。当您获得外部网页的 DocumentComplete 事件时,您就知道您已经完成了。您应该能够使用IWebBrowser2::TopLevelContainer()的托管等效项来确定这一点。
Beware, however, the website itself can trigger more frame navigations anytime it wants, so you never know if a page is truly done forever. The best you can do is keep a count of all the BeforeNavigates you see and decrement the count when you get a DocumentComplete.
但是请注意,网站本身可以随时触发更多的框架导航,因此您永远不知道页面是否真的永远完成了。您能做的最好的事情是记录您看到的所有 BeforeNavigates 并在您获得 DocumentComplete 时减少计数。
Edit: Here's the managed docs: TopLevelContainer.
编辑:这是托管文档:TopLevelContainer。
回答by Kamil Szot
My approach to doing something when page is completely loaded(including frames) is something like this:
我在页面完全加载(包括框架)时做某事的方法是这样的:
using System.Windows.Forms;
protected delegate void Procedure();
private void executeAfterLoadingComplete(Procedure doNext) {
WebBrowserDocumentCompletedEventHandler handler = null;
handler = delegate(object o, WebBrowserDocumentCompletedEventArgs e)
{
ie.DocumentCompleted -= handler;
Timer timer = new Timer();
EventHandler checker = delegate(object o1, EventArgs e1)
{
if (WebBrowserReadyState.Complete == ie.ReadyState)
{
timer.Dispose();
doNext();
}
};
timer.Tick += checker;
timer.Interval = 200;
timer.Start();
};
ie.DocumentCompleted += handler;
}
From my other approaches I learned some "don't"-s:
从我的其他方法中,我学到了一些“不要”:
- don't try to bend the spoon ... ;-)
- don't try to build elaborate construct using DocumentComplete, Frames, HtmlWindow.Load events. Your solution will be fragile if working at all.
- don't use
System.Timers.Timer
instead ofWindows.Forms.Timer
, strange errors will begin to occur in strange places if you do, due to timer running on different thread that the rest of your app. - don't use just Timer without DocumentComplete because it may fire before your page even begins to load and will execute your code prematurely.
- 不要试图弯曲勺子...... ;-)
- 不要尝试使用 DocumentComplete、Frames、HtmlWindow.Load 事件构建复杂的构造。如果完全有效,您的解决方案将是脆弱的。
- 不要使用
System.Timers.Timer
代替Windows.Forms.Timer
,如果你这样做了,奇怪的错误会开始发生在奇怪的地方,因为计时器运行在与你的应用程序的其余部分不同的线程上。 - 不要在没有 DocumentComplete 的情况下只使用 Timer,因为它可能会在您的页面开始加载之前触发,并且会过早地执行您的代码。
回答by Daniel Stutzbach
Here's how I solved the problem in my application:
这是我在应用程序中解决问题的方法:
private void wbPost_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url != wbPost.Url)
return;
/* Document now loaded */
}
回答by Jeppoo
I just use the webBrowser.StatusText method. When it says "Done" everything is loaded! Or am I missing something?
我只是使用 webBrowser.StatusText 方法。当它说“完成”时,一切都已加载!或者我错过了什么?