WebBrowser.Document.Body is always null

你说的曾经没有我的故事 提交于 2019-12-12 08:27:46

问题


I have a WebBrowser document set to be in edit mode. I am trying to manipulate the inner text of the body element by using WebBrowser.Document.Body.InnerText, however, WebBrowser.Document.Body remains null.

Here is the code where I create the document contents:

private WebBrowser HtmlEditor = new WebBrowser();
public HtmlEditControl()
{
    InitializeComponent();
    HtmlEditor.DocumentText = "<html><body></body></html>";
    myDoc = (IHTMLDocument2)HtmlEditor.Document.DomDocument;
    myDoc.designMode = "On";
    HtmlEditor.Refresh(WebBrowserRefreshOption.Completely);
    myContentsChanged = false;
}

I can edit code and everything fine, but I don't understand why HtmlEditor.Document.Body remains null. I know I could always just reset the document body whenever I need to load text into the form, but I would prefer to understand why this is behaving the way it is, if nothing else then for the knowledge.

Any help on this is greatly appreciated.


回答1:


You have to wait for the Web Browser's DocumentCompleted event to fire for the DomDocument.Body to not be null. I just tested this to verify. I suppose the question still remains: how are you able to edit through the underlying COM interface when the document has not completely loaded?

I checked to see if the IHTMLDocument2 pointers were the same in DocumentCompleted and the constructor. They are, which might indicate that the underlying COM object reuses a single HTML document object. It seems like any changes you make in the constructor at least have a pretty good chance of getting overwritten or throwing an exception.

For example, if I do this in the constructor, I get an error:

IHTMLDocument2 p1 = (IHTMLDocument2) HTMLEditor.Document.DomDocument;

p1.title = "Hello world!";

If I do the same in a DocumentCompleted handler, it works fine.

Hope this helps. Thanks.




回答2:


Use DocumentCompleted event first, it occurs when the WebBrowser control finishes loading a document:

public HtmlEditControl()
{
    InitializeComponent();
    HtmlEditor.DocumentText = "<html><body></body></html>";
    HtmlEditor.DocumentCompleted += HtmlEditorDocumentCompleted;
}

void HtmlEditorDocumentCompleted(object sender, 
                                 WebBrowserDocumentCompletedEventArgs e)
{
    myDoc = (IHTMLDocument2)((WebBrowser)sender).Document.DomDocument;
    myDoc.designMode = "On";
    HtmlEditor.Refresh(WebBrowserRefreshOption.Completely);
    myContentsChanged = false;
}

or simple way:

public HtmlEditControl()
{
    InitializeComponent();
    HtmlEditor.DocumentText = "<html><body></body></html>";
    HtmlEditor.DocumentCompleted += (sender, e) =>
            {
                myDoc = (IHTMLDocument2) HtmlEditor.Document.DomDocument;
                myDoc.designMode = "On";
                HtmlEditor.Refresh(WebBrowserRefreshOption.Completely);
                myContentsChanged = false;
            };
}



回答3:


You need to let the WebBrowser control to work alone a bit to give it some time to set the Document.Body property.

I do that by calling Application.DoEvents();.

For instance in your code:

private WebBrowser HtmlEditor = new WebBrowser();
public HtmlEditControl()
{
    InitializeComponent();
    HtmlEditor.DocumentText = "<html><body></body></html>";

    // Let's leave the WebBrowser control working alone.
    while (HtmlEditor.Document.Body == null)
    {
        Application.DoEvents();
    }

    myDoc = (IHTMLDocument2)HtmlEditor.Document.DomDocument;
    myDoc.designMode = "On";
    HtmlEditor.Refresh(WebBrowserRefreshOption.Completely);
    myContentsChanged = false;
}



回答4:


if (HtmlEditor.Document.Body == null)
{
   HtmlEditor.Document.OpenNew(false).Write(@"<html><body><div id=""editable""></div></body></html>");
}
HtmlEditor.Document.Body.SetAttribute("contentEditable", "true");


来源:https://stackoverflow.com/questions/8141061/webbrowser-document-body-is-always-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!