WebBrowser Navigation Methods

  • Thread starter Thread starter King Coffee
  • Start date Start date
K

King Coffee

Hi,

I'm trying to use the webBrowser.Navigate control in a C# app. If I put it
in the Form_Load method it works fine. But if I put it a Button_Click
method, it does not load the webBrowser.Document property or window.

Thanks,
King
 
PS: If I navigate to a local htm file it button method works. But if I try
to navigate to a network URL, it fails.

King
 
King said:
Hi,

I'm trying to use the webBrowser.Navigate control in a C# app. If I put
it in the Form_Load method it works fine. But if I put it a Button_Click
method, it does not load the webBrowser.Document property or window.

Works fine for me. Post the code that doesn't work. And be more
explicit about what "load the webBrowser.Document property or window"
means, as well as exactly what "it fails" means (including any error
message, if there is one).

Pete
 
Peter Duniho said:
Works fine for me. Post the code that doesn't work. And be more explicit
about what "load the webBrowser.Document property or window" means, as
well as exactly what "it fails" means (including any error message, if
there is one).

Pete

Thanks Pete,

The com visibility is for other features not listed.
If I navigate to the URL in the Form1_Load method, it works.
But if I navigate to the URL in the button1_Click method, it does not
works.
Error massage states that the webBrowser1.Document object is null.

I'm assuming that the webBrowser1.Navigate("http://msdn.microsoft.com")
method call loads the webBrowser1 control properties.

The none functioning code is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;

namespace Apartment_Listing
{
[ComVisible(true)]
public partial class Form1 : Form
{
string Apartments;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//webBrowser1.Navigate("http://msdn.microsoft.com");
}

private void button1_Click(object sender, System.EventArgs e)
{
string htmlOut = null;
webBrowser1.Navigate("http://msdn.microsoft.com");

while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(500);

this.Text = webBrowser1.Document.Title;
ProcessPage(webBrowser1.Document, ref htmlOut);
webBrowser2.DocumentText = htmlOut;
}

private void ProcessPage(HtmlDocument doc, ref string htmlOut)
{
htmlOut += "<br />New Page<br />";
while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(1000);

// Deleted for brevity...
}

private void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
}

Thanks,
King
 
Peter Duniho said:
Works fine for me. Post the code that doesn't work. And be more
explicit about what "load the webBrowser.Document property or window"
means, as well as exactly what "it fails" means (including any error
message, if there is one).

Pete

Thanks Pete,

The com visibility is for other features not listed.
If I navigate to the URL in the Form1_Load method, it works.
But if I navigate to the URL in the button1_Click method, it does not
works.
Error massage states that the webBrowser1.Document object is null.

I'm assuming that the webBrowser1.Navigate("http://msdn.microsoft.com")
method call loads the webBrowser1 control properties.

The none functioning code is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;

namespace Apartment_Listing
{
[ComVisible(true)]
public partial class Form1 : Form
{
string Apartments;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//webBrowser1.Navigate("http://msdn.microsoft.com");
}

private void button1_Click(object sender, System.EventArgs e)
{
string htmlOut = null;
webBrowser1.Navigate("http://msdn.microsoft.com");

while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(500);

this.Text = webBrowser1.Document.Title;
ProcessPage(webBrowser1.Document, ref htmlOut);
webBrowser2.DocumentText = htmlOut;
}

private void ProcessPage(HtmlDocument doc, ref string htmlOut)
{
htmlOut += "<br />New Page<br />";
while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(1000);

// Deleted for brevity...
}

private void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
}

Thanks,
King

You need to process the DocumentCompleted event rather than waiting for
IsBusy to be false. Set up the handler for
webBrowser1.DocumentCompleted to do the work that is after your
..Navigate call. It looks like you started to set up this event handler
at some time. If you had a problem with that, let us know.
 
Thanks Mike,

How do I pass an parameter to WebBrowserDocumentCompletedEventArgs... ? Use
a class member variable?
Also, I need to call ProcessPage() recursively, to process the current page,
and then a new page
if the current page contain an "Next" page anchor.

The ProcessPage() looks something like this:

private void ProcessPage(HtmlDocument doc, ref string htmlOut)
{
string Name;
string Phone;
string Address;
string Locality;

htmlOut += "<br />New Page<br />";
while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(500);

HtmlElement element = null;
HtmlElementCollection elements = null;
HtmlElement firstElem = doc.GetElementById("results_header");

if ((element =
doc.GetElementById("results_multiple_listings_container"))
!= null)
{
elements = element.GetElementsByTagName("li"); //li childs
// Parse the current page contents for listings
foreach (HtmlElement li in elements)
{
if (li.Children.Count == 0) continue;
HtmlElementCollection header =
li.Children[0].GetElementsByTagName("H3");
Name = header[0].InnerText;
HtmlElementCollection Ps =
li.Children[0].GetElementsByTagName("P");
Address = Ps[1].InnerText;
Locality = Ps[2].InnerText;
Phone = Ps[3].InnerText;

Debug.WriteLine(Name + ", " + Address + ", " + Phone);
}

// Do the next page, if it exists
element = null;
elements = doc.Body.GetElementsByTagName("a");
foreach(HtmlElement a in elements)
{
if (a.InnerText == "Next")
{
string href = a.GetAttribute("href");
webBrowser1.Navigate(href);
ProcessPage(webBrowser1.Document, ref htmlOut);
break;
}
}
}



Family Tree Mike said:
Peter Duniho said:
Works fine for me. Post the code that doesn't work. And be more
explicit about what "load the webBrowser.Document property or window"
means, as well as exactly what "it fails" means (including any error
message, if there is one).

Pete

Thanks Pete,

The com visibility is for other features not listed.
If I navigate to the URL in the Form1_Load method, it works.
But if I navigate to the URL in the button1_Click method, it does not
works.
Error massage states that the webBrowser1.Document object is null.

I'm assuming that the webBrowser1.Navigate("http://msdn.microsoft.com")
method call loads the webBrowser1 control properties.

The none functioning code is as follows:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Diagnostics;

namespace Apartment_Listing
{
[ComVisible(true)]
public partial class Form1 : Form
{
string Apartments;
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
//webBrowser1.Navigate("http://msdn.microsoft.com");
}

private void button1_Click(object sender, System.EventArgs e)
{
string htmlOut = null;
webBrowser1.Navigate("http://msdn.microsoft.com");

while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(500);

this.Text = webBrowser1.Document.Title;
ProcessPage(webBrowser1.Document, ref htmlOut);
webBrowser2.DocumentText = htmlOut;
}

private void ProcessPage(HtmlDocument doc, ref string htmlOut)
{
htmlOut += "<br />New Page<br />";
while (webBrowser1.IsBusy) System.Threading.Thread.Sleep(1000);

// Deleted for brevity...
}

private void webBrowser1_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
}

Thanks,
King

You need to process the DocumentCompleted event rather than waiting for
IsBusy to be false. Set up the handler for webBrowser1.DocumentCompleted
to do the work that is after your .Navigate call. It looks like you
started to set up this event handler at some time. If you had a problem
with that, let us know.
 
Thanks Mike,

How do I pass an parameter to WebBrowserDocumentCompletedEventArgs... ?
Use a class member variable?

You don't pass anything in the eventargs. The web browser control is
passing this information to your code. What parameter do you think you
need in the handler?

Also, I need to call ProcessPage() recursively, to process the current
page, and then a new page
if the current page contain an "Next" page anchor.

The ProcessPage() looks something like this:

Well, I think you should be calling Navigate multiple times and handling
the DocumentComplete as a collector of the info you want to keep. It
kind of sounds like a spider...

It probably would be easier to use a webclient rather than a web browser
control. If you stick with the web browser control, I highly recommend
not using the IsBusy property, and getting to understand the events that
are raised. You'll have nothing but troubles if you depend on the
IsBusy flag.
 
Thanks Mike,

I will investigate the WebClient control. Yes, it functions like a spider
because some of the page output listing are partitioned over over multiple
pages. I think I can collect the current page info in a static string as I
nest through the multiple page listing. Also, I want to call navigate
multiple times. However, I need to think or consider how the
DocumentComplete method distinguish the navigate calling instances.

Thanks,
King
 
Hi,

The problem appears to be
"webBrowser1.Navigate("http://msdn.microsoft.com");" does not connect to the
web if ran within a button. However, it will process a local file from a
button. I need to programmatically change the internet page and re-read it.
Is there a workaround like setting the webBrowser URL property ?

King
 
King said:
Hi,

The problem appears to be
"webBrowser1.Navigate("http://msdn.microsoft.com");" does not connect to
the web if ran within a button. However, it will process a local file
from a button. I need to programmatically change the internet page and
re-read it. Is there a workaround like setting the webBrowser URL
property ?

If setting the URL property were a useful workaround, surely you'd have
determined that already by trying it yourself.

It seems to me that Mike's suggestion is actually the explanation you
should be looking at. It's simply not true that there's a material
difference between calling the Navigate() method from the Load event
handler and a button's Click event handler.

It _is_ true that loading a page over the Internet will take longer than
locally, and so if you have a bug that's timing dependent (such as
trying to view the downloaded document before the DocumentComplete event
has been raised), you may see the bug only when you load a document over
the Internet but not from a local file.

You should stop looking for a workaround to a non-existent problem in
the API, and just fix the code the way that Mike suggests.

Pete
 
Hi,

I tried Mike's suggest of adding the code to the DocumentComplete handler...
Then I placed a breakpoint within that event. But the navigation call from
within the button event, never branched to it. Also, I do not know if people
are using the URL property as a workaround since I do not know how to
specify it... it's not a simple string specifier. I now think I'm fighting a
bug. The loading event may be long enough to avoid timing concerns.

King
 
Hi,

I tried Mike's suggest of adding the code to the DocumentComplete
handler... Then I placed a breakpoint within that event. But the
navigation call from within the button event, never branched to it.
Also, I do not know if people are using the URL property as a workaround
since I do not know how to specify it... it's not a simple string
specifier. I now think I'm fighting a bug. The loading event may be long
enough to avoid timing concerns.

King

I'm pretty sure the only way that what you are describing can happen is
for the event handler to be unsubscribed by your code. There are some
links to the fact that this event is not fired if the control is not
visible, but you haven't indicated you are changing visibility.
 
Hi Mike,

The best way to demonstrate that the code is functioning different depending
on the event handler... is for you to see if it runs the same way on your
system. If you don't mind, I would like to email you a small zip file of the
test project I'm using. So, can I email it to the email address you list
below ?

King
 
Hi Mike,

The best way to demonstrate that the code is functioning different
depending on the event handler... is for you to see if it runs the same
way on your system. If you don't mind, I would like to email you a small
zip file of the test project I'm using. So, can I email it to the email
address you list below ?

King

I cannot promise how quickly I will look at it, but go ahead.
FamilyTreeMike at Comcast.net.
 
Family Tree Mike said:
I cannot promise how quickly I will look at it, but go ahead.
FamilyTreeMike at Comcast.net.

Your code did not instantiate the document completed event handler.

Once I changed your Form1_Load() method to the following:

private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler
(webBrowser1_DocumentCompleted);
webBrowser1.Navigate("http://msdn.microsoft.com");
}

Both the button click, and the form load ended up inside the handler
function, as expected.

Note that the documentcompleted event fires multiple times for pages with
multiple frames, as this page you reference does. Here is a link on handling
that situation:
http://stackoverflow.com/questions/840813/how-to-use-webbrowser-control-documentcompleted-event-in-c


Mike
 
Back
Top