缓存和重用HtmlElement对象的树

时间:2009-02-16 19:06:03

标签: browser webbrowser-control dom

我在项目中使用WebBrowser控件来显示在运行时生成/操作的复杂HTML文档。

我注意到,通过创建HtmlElement对象以编程方式从C#构造DOM比生成HTML字符串并将其传递给WebBrowser慢约3倍,后者又会解析它以生成DOM 。在漫长的文档之间导航时,这两种方式都会产生明显的延迟。

我正在寻找在同一WebBrowser控件中切换多个文档的最快方法,理想情况下无需为每个文档重复生成DOM树。是否可以在我的程序中的某处缓存HtmlElement个对象树,然后根据需要将它们重新插入WebBrowser

5 个答案:

答案 0 :(得分:2)

我将根据原生win32 COM API描述解决方案;在C#中编写互操作(或在pinvoke.net上找到它)应该不会太困难。或者,您可能需要使用托管对象公开的特性来获取本地特性。

您不太可能比IE的解析器更快地构建DOM,因此创建一个空白的HTMLDocument(在本机代码中为CoCreateInstance(CLSID_HTMLDocument))和QueryInterface()为其IMarkupServices实现的HTMLDocument。还使用IMarkupServices :: CreateMarkupPointer()方法创建两个IMarkupPointers。

接下来调用IMarkupServices :: ParseString()来解析你的HTML。这将为您提供指向包含DOM的IMarkupContainer的指针,以及指向DOM的开头和结尾的两个IMarkupPointer。现在,您可以使用IMarkupServices :: Move()将数据从一个IMarkupContainer移动到另一个IMarkupContainer。

因此,您将使用的一般方案是使用单个HTMLDocument,它是您的“显示”文档,它与IMarkupContainer(您可以只使用QueryInterface())相关联。然后你有一个向量或列表或所有非显示标记容器中的任何一个。然后,您只需为显示文档创建一个标记指针,调用IMarkupPointer :: MoveToContainer(displayDocumentContainer,true),然后使用它将显示容器中的内容移动到不显示容器,反之亦然。

有一点需要注意:您必须只能在创建它们的线程上访问这些对象,或者获取它们。所有IE对象都是STA对象。如果您需要多线程访问,则必须编组。

如果您有具体的跟进问题,请与我们联系。

参考文献:

答案 1 :(得分:2)

这样做

// 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);

答案 2 :(得分:1)

我真的需要了解更多关于如何生成这些文档的信息。将数据放入XML文档然后使用XSL转换将数据转换为HTML并将其传递给WebBrowser控件可能会更快。

.NET的XSLT实现的好处在于它需要XSL源并将其编译为临时程序集以加速转换。

如果您决定走这条路,请查看MVP.XML项目,该项目为库存XSLT实现添加了一些不错的exslt功能。

答案 3 :(得分:0)

也许不是缓存DOM,你只需在表单上的几个WebBrowser控件之间切换 - 只有活动的控件可见?

答案 4 :(得分:0)

你可以这样做吗?

  • 创建要在DIV中显示的内容
  • 在不可见的DIV中创建辅助内容(在后台)
  • 通过使用可见性
  • 来交换内容