views:

1206

answers:

5

I'm trying to load an html document into a WebBrowser control, but I'm at my wits end. Here's a sample:

public void Button_Click(object sender, EventArgs e)
{
    webBrowser1.DocumentCompleted += new  WebBrowserDocumentCompletedEventHandler(wb_c);
    webBrowser1.DocumentText = "<html>foo</html>";

    // The documenttext property is NOT what was set above.  
    // No exception is thrown.  It's always "<html></html>\0", however.
    // This line setting the title throws a HRESULT COM error.
    webBrowser1.Document.Title = "foobar!";
}

The wb_c event handler is never called, either. The webbrowser control is defined as a control on the form. The form itself consists of only the browser and the button.

Does anyone have any ideas? I've used this class before without any issues, but this time the .Net gods are denying me! My end goal is to print the rendered document, but right now I can't even get it to accept my HTML. Maybe I need some holy water or something.

Edit: If the Title line is removed above, the wb_c event handler is never getting triggered. It's as though there's something wrong with the COM component itself, or something.

Edit 2: By popular demand, here is a complete blob of my code.

public partial class Form2 : Form
{
    [STAThread]
    public static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form2());
    }


    public Form2()
    {
        InitializeComponent();
        webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_c);
    }

    void wb_c(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        throw new Exception("The method or operation is not implemented.");
    }

    private void button1_Click(object sender, EventArgs e)
    {
        webBrowser1.DocumentText = "<html>foo</html>";
    }
}



partial class Form2
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {
        this.webBrowser1 = new System.Windows.Forms.WebBrowser();
        this.button1 = new System.Windows.Forms.Button();
        this.SuspendLayout();
        // 
        // webBrowser1
        // 
        this.webBrowser1.Location = new System.Drawing.Point(12, 12);
        this.webBrowser1.MinimumSize = new System.Drawing.Size(20, 20);
        this.webBrowser1.Name = "webBrowser1";
        this.webBrowser1.Size = new System.Drawing.Size(117, 99);
        this.webBrowser1.TabIndex = 0;
        // 
        // button1
        // 
        this.button1.Location = new System.Drawing.Point(90, 165);
        this.button1.Name = "button1";
        this.button1.Size = new System.Drawing.Size(75, 23);
        this.button1.TabIndex = 1;
        this.button1.Text = "button1";
        this.button1.UseVisualStyleBackColor = true;
        this.button1.Click += new System.EventHandler(this.button1_Click);
        // 
        // Form2
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(292, 266);
        this.Controls.Add(this.button1);
        this.Controls.Add(this.webBrowser1);
        this.Name = "Form2";
        this.Text = "Form2";
        this.Load += new System.EventHandler(this.Form2_Load);
        this.ResumeLayout(false);

    }

    #endregion

    private System.Windows.Forms.WebBrowser webBrowser1;
    private System.Windows.Forms.Button button1;
}

This is a .Net 2.0 project running in VS 2005. System.Windows.Forms.dll is v2.0.50727.

EDIT 3: Adding this line to the end of the Form2 constructor:

webBrowser1.Navigate("about:blank");

Does trigger the event handler, but it doesn't otherwise affect the behavior of the code when setting the document text. Setting a breakpoint after the webBrowser1.Document.Text line still gives the same "\0" string, and trying to set the title still gives a COM HERROR.

+3  A: 

Try moving the line:

webBrowser1.Document.Title = "foobar!";

into your wb_c method. I think the problem is that when you're calling it, the Document property isn't completley set yet, and you're getting a null reference exception. If you wait till the page is loaded, you should be ok.

UPDATE: Tried your sample, and your event handler IS getting called, however I suspect it's being called from another thread. Therefore, it gets to the line where the Exception is thrown, but you're never actually seeing it, because it's in another thread. Take out the line that throws the exception, and replace it with:

webBrowser1.Document.Title = "foobar!";

That should do the trick.

BFree
The wb_c handler is never getting triggered, even when the title line is removed.
yodaj007
That's odd, I created a simple test app using your code, and the handler gets called and set the DocumentTitle with no problems.
BFree
Yep, that(@Bfree's suggestion) is the correct way.
Cerebrus
That is odd. I get the same results as BFree. Perhaps we need to see more of the code.
Jeff Yates
I've updated the question in response to your queries.
yodaj007
I suspect that the exception is getting swallowed by the browser control. It's not on a different thread, it's just capturing all the exceptions (probably desperately trying to reign in the Browser COM control's tendency to cause problems).
Jeff Yates
A: 

Document loading is asynchronous so by the time you set the Title, there is no guarantee that the document has actually loaded. You need to handle the appropriate browser events to detect when navigation is complete before trying to alter the document.

Update

In all situations where I've used the browser, I've had to navigate to the about:blank page first before I could modify the document. Perhaps you should try this before setting the DocumentText.

Jeff Yates
The DocumentCompleted event is never getting triggered.
yodaj007
A: 

Before you can manipulate the Document you need to execute the navigate command. To use the WebBrowser to construct a HTML page from scratch just navigate to "about:blank" like so:

WebBrowser browser = new WebBrowser();
browser.Navigate("about:blank");
browser.Document.Write(html);

Then use the InnerHtml on the root element and not the DocumentText property to apply Html as you are.

Rob
A: 

Has this been resolved? I'm also having the same issue.

A: 

I use the method above that uses about:blank and it works ok! I published an article about this method yesterday and today i've just found this topic here :) My article here: http://starikovs.com/2009/11/25/set-html-webbrowser-csharp/

Vacheslav