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.
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.
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;
};
}
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;
}
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