Feb 12 2006

WebBrowser.DocumentText doesn't always update the browser contents

Category: IT Related | .NetRory Primrose @ 00:23

I have been developing some new software which uses the WebBrowser control. Depending on what is selected in a TreeView control, the browser will be instructed to load some HTML that has been created and manipulated in memory.

The problem I have encountered is that once the HTML has been determined, setting the DocumentText property hasn't been updating what is displayed in the browser. It only displays the HTML that was orginally assigned to the control. The reason for this not working is hinted at in the help documentation for the Document Text property. The documentation says this:

Use this property when you want to manipulate the contents of an HTML page displayed in the WebBrowser control using string processing tools. You can use this property, for example, to load pages from a database or to analyze pages using regular expressions. When you set this property, the WebBrowser control automatically navigates to the about:blank URL before loading the specified text. This means that the Navigating, Navigated, and DocumentCompleted events occur when you set this property, and the value of the Url property is no longer meaningful.

For my application, I have set up the WebBrowser control to be as restricted as possible because I don't want my application to look like a browser. For example, I don't want the browsers context menu to be displayed when the user right-clicks on it. One of the properties I changed was to set AllowNavigation = false. The help description for the AllowNavigation property says this:

Gets or sets a value indicating whether the control can navigate to another page after its initial page has been loaded.

If you fire up Reflector and find the WebBrowser.DocumentText property you will see that internally, setting the WebBrowser.DocumentText property will create a MemoryStream with the new text value and then the stream is assigned to the WebBrowser.DocumentStream property. Reflector shows the DocumentStream property code to be this:

public Stream DocumentStream
{
      get
      {
            HtmlDocument document1 = this.Document;
            if (document1 == null)
            {
                  return null;
            }
            UnsafeNativeMethods.IPersistStreamInit init1 = document1.DomDocument as UnsafeNativeMethods.IPersistStreamInit;
            if (init1 == null)
            {
                  return null;
            }
            MemoryStream stream1 = new MemoryStream();
            UnsafeNativeMethods.IStream stream2 = new UnsafeNativeMethods.ComStreamFromDataStream(stream1);
            init1.Save(stream2, false);
            return new MemoryStream(stream1.GetBuffer(), 0, (int) stream1.Length, false);
      }
      set
      {
            this.documentStreamToSetOnLoad = value;
            try
            {
                  this.webBrowserState[2] = true;
                  this.Url = new Uri("about:blank");
            }
            finally
            {
                  this.webBrowserState[2] = false;
            }
      }
}

When a new stream is assigned to DocumentStream, it will attempt to navigate to about:blank as the documentation says. The code here indicates that the stream data will be populated into the browser after it has navigated to about:blank. The hitch here is that if the navigation fails, you are none the wiser that the process has failed and the new document text won't be loaded. My problem with the code here is that the try block around the navigate swallows the exception, hence the document content doesn't change and you won't know why.

Basically, setting AllowNavigation = false cripples the DocumentText and DocumentStream properties as well as the navigation methods.

Tags:

Comments (11) -

1.
PK PK says:

This really sucks. This particular "issue" should be added to the documentation.

Have you found a workaround that doesn't require setting AllowNavigation to true?

2.
Rory Primrose Rory Primrose says:

Nope. By using Reflector to review the Microsoft code, I don't see that there is anything else that can be done about it.

3.
John John says:

Has anyone tried setting AllowNavigation to true just before setting DocumentText, then switching AllowNavigation back to false?

4.
Rory Primrose Rory Primrose says:

Hi John.

I just tested that and it won't work because the navigation would be happening on a different thread. This means that if you set AllowNavigation back to false, the browser will not have had the chance to navigate to about:blank (and therefore set the new contents) before that line of code fires.

The closest solution to what you have said would be to enable AllowNavigation, set the document contents and then wait for the browsers DocumentComplete event before setting AllowNavigation back to false. This means that there is a window of time (between your set contents and the document complete) in which navigations can happen. This may or may not be an appropriate solution depending on your requirements.

5.
Johnny Johnny says:

I have set AllowNavigation to True but I still end up with the same problem as you mention. I have used a WebBrowser control to show up a map from ZoomIn.co.nz, and dynamically I try to change the DocumentText so that I can move the map from one location to another.



It works if I am only changing JavaScript variable, but it wont work if I am changing JavaScript coding. It is very wierd to me. I use simple String.Replace() for both and I have extracted the changed text and they are alright. It is just when I assign them to the DocumentText then one is working while the other is not.

6.
Luca Luca says:

Hi Rory,
this is my code:
private void Method1(parameters....) {
...
this.webBrowserFeed.AllowNavigation = true;
            this.webBrowserFeed.DocumentText =
            @" ...html code ... ";
...
}
private void webBrowserFeed_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            this.webBrowserFeed.AllowNavigation = false;
        }

I tried your solution (May 3, 2006 11:03 PM) of setting AllowNavigation back to false on webBrowserFeed_DocumentCompleted event, because sometime property DocumentText is setted twice and the second time DocumentText doesn't work.
Unfortunately when DocumentText is setted the first time, event DocumentCompleted is not fired.
Do you have a suggestion?

Thanks in advance,
Luca

7.
Yves BABITCH Yves BABITCH says:

Hi !

Try this ...

<...>
      SetHTMLText(HTMLText);
<...>

    private void SetHTMLText(string _text)
    {
      webBrowserMedicalCases.Tag = false;
      webBrowserMedicalCases.DocumentText = _text;

      while (!((bool)webBrowserMedicalCases.Tag))
      {
        Application.DoEvents();
        Thread.Sleep(10);
      }
    }

    private void webBrowserMedicalCases_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
      webBrowserMedicalCases.Tag = true;
    }

I am using Tag property of the webBrowser object as a boolean... It's not very clean, but this solution works.
And this works fine with AllowNavigation set to true or false.

Yves B.

8.
Korayem Korayem says:

Here is the solution



            if (wbResponse.Document != null)
            {
                wbResponse.Document.OpenNew(true);
                wbResponse.Document.Write(serverResponse);
            }
            else
            {
                wbResponse.DocumentText = serverResponse;

            }



Original solution posted by "James Booze" geekswithblogs.net/.../62961.aspx

9.
ayan ayan says:

Thanks Korayem, for the excellent suggestion!!!

10.
Gabriel Gabriel says:

Just set the AllowNavigation to true before you change the content and then set it to false in the DocumentCompleted event

11.
Panagiotis Panagiotis Greece says:

the best solution I found so far is to use

<Your WebBrowser>.Document.Body.InnerHtml

instead of DocumentText

it works ok for me even when AllowNavigation = false

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading