问题
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