构建HtmlElement对象树

时间:2009-03-10 19:44:19

标签: html browser webbrowser-control dom

我在C#桌面应用程序中使用MSIE WebBrowser控件,我正在寻找一种方法来构建和维护此控件之外的HtmlElement个对象的树。我试图在多个复杂页面之间快速切换,而不会产生每次重新解析HTML的开销(并且我不想维护根据需要显示/隐藏的多个控件)。 我发现a)我只能通过控件HtmlElement和b)创建HtmlDocument个对象,一旦我从控件的HtmlElement中移除HtmlDocument个对象的“主干”,它尽管我一直保持对根元素的强烈引用,但“死了”。 我怎么能这样做?

P.S。如果他们允许我完成上述操作,我愿意考虑其他浏览器控件(例如Gecko)。

4 个答案:

答案 0 :(得分:4)

这样做

// On screen webbrowser control
webBrowserControl.Navigate("about:blank");
webBrowserControl.Document.Write("<div id=\"div1\">This will change</div>");
var elementToReplace = webBrowserControl.Document.GetElementById("div1");
var nodeToReplace = elementToReplace.DomElement as mshtml.IHTMLDOMNode;

// In memory webbrowser control to load fragement into
// It needs this base object as it is a COM control
var webBrowserFragement = new WebBrowser();
webBrowserFragement.Navigate("about:blank");
webBrowserFragement.Document.Write("<div id=\"div1\">Hello World!</div>");
var elementReplacement = webBrowserFragement.Document.GetElementById("div1");
var nodeReplacement = elementReplacement.DomElement as mshtml.IHTMLDOMNode;

// The magic happens here!
nodeToReplace.replaceNode(nodeReplacement);

我怀疑这会改善性能,因为文本渲染器很快,如果你有一个隐藏div的大页面或者其他对象的内存中有多个div,所消耗的内存仍然是相同的吗?

答案 1 :(得分:2)

您可以使用MSHTML库(mshtml.dll)来实现此目的。基本上你会使用一个about:blank页面,然后动态地从中写入和删除内容。

请参阅此blog post on this subject

您还可以编写一个自定义界面包装器,它可以从mshtml中公开您需要的功能,而不是引用整个内容(大约8MB),并且在VS中使用f12非常容易。

答案 2 :(得分:1)

你真的需要将它们真正地移除吗?把你的“分支”留在DOM中作为DIV的子节点,其样式=“display:none”。这样他们就是真实的,直播的DOM对象但不可见。

答案 3 :(得分:0)

我认为你也可以使用htmlagilitypack 它允许您解析一次,使用XPath或通过迭代器查询HTML树,并在完成后使用save方法重写树。 根据你的结构,你可能只是在类周围创建一个适配器,因为它只适用于整个html文档而你只想要它在元素上,但这应该不会太难。