3

I have a webpage, and an input button on it. Clicking on this button, in a specific div are loaded some data. My problem is that I can't catch this data.

The following code is my attempt to solve this problem, but without success.

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    HtmlElement div_result = webBrowser1.Document.GetElementById("div_result");
    div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler));
}
private void resultEventHandler(object sender, EventArgs e)
{
    MessageBox.Show("Loaded");
}

If I click on input button, div's content is modified, but the resultEventHandler does not fire.

So, I have two questions:

  1. Where is my fault in this code?
  2. Is there a "normal way"(I mean without using timers or Aplication.DoEvents()) to work with ajax using WebBrowser control in C#?
abatishchev
  • 98,240
  • 88
  • 296
  • 433
zerocube
  • 31
  • 2
  • Is it because "Changing the innerText or innerHTML of child elements will not cause the onpropertychange event to fire for the parent element."? Because when content changes no property of DIV need to change. http://msdn.microsoft.com/en-us/library/ie/ms536956(v=vs.85).aspx – aliassce Jun 25 '14 at 11:01

3 Answers3

0

Changing the innerText or innerHTML of child elements will not cause the onpropertychange event to fire for the parent element.

HMarioD
  • 842
  • 10
  • 18
  • I read this note from msdn, but I don't have child elements. I have a very [simple webpage](http://fast-index.ru/wbajax.php) , that I made special for this experiment. – zerocube Dec 24 '12 at 16:34
0

I cannot tell why HtmlElement events do not work for you. But I had the same problem and resolved it by using COM wrappers:

mshtml.HTMLDocumentClass doc = (mshtml.HTMLDocumentClass)webBrowser1.Document.DomDocument;
mshtml.IHTMLElement2 div_result = (mshtml.IHTMLElement2)doc.getElementById("div_result");
mshtml.HTMLElementEvents2_Event events = (mshtml.HTMLElementEvents2_Event)div_result;
events.onpropertychange += resultEventHandler;
Paul B.
  • 2,394
  • 27
  • 47
0

This may be too late but here it is anyways in case you are still wondering:

1 - HtmlElement div_result = webBrowser1.Document.GetElementById("div_result"); Line #1 executes when the web page has loaded and the DocumentCompleted event has been called by the browser. Inside the event handler you first retrieve a pointer to the DOM element "div_result" and you assign an HtmlElement type variable named div_result.

2 - div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler)); Line #2 - registers the "onpropertychange" event and assigns the method resultEventHandler as the listener method.

Every time you click on the button on your web page, the button (which I assume) is in a form that gets submitted which causes the web page to load; by the way you did not specify which post method you are using when the button is clicked (get or post). When the web page download completes and the DOM element tree is constructed your DocumentCompleted event is called. You're DocumentCompleted event handler method performed the instructions described above.

Every time you click your button, you web page is reloaded and you reassign the event listener for the onpropertychange event. You are only assigning the event listener. The event will never be called. It will just be defined every time you click the button. You have a classic which came first chicken, or egg problem. But in your case, your chicken is the button click event causing the DocumentCompleted method to run which resets the state of all variables in the method, and your egg is wanting a pointer to the DIV element's onpropertychange event before the button is clicked on the web page . How do you assign an event listener to an htmlelement before you can get a pointer from the DOM which has not been constructed? Put a Boolean flag variable in the class that contains the DocumentCompleted method and set its initial state. Move the div_result variable outside of the DocumentCompleted method to increase its scope and to save its state across a button click event. This way, you will get a pointer to your div element and set its onpropertychange event listener the first time the web page is downloaded. Add a test if you just want to set a pointer to the DIV element's onpropertychange event listener just once (I put one in the sample code below), and the next time you click your button, your event will fire. NOTE! Make sure you do not add, or delete any element to your web page after you store a pointer to any of the web page's elements or their events. Otherwise you will have to reparse the DOM to get a pointer to the Element's new position in the DOM tree.

//See below:

class SomeClass
{
    bool DocumentHasLoaded = false;
    HtmlElement div_result = null;

    //Constructor and other methods go here....

    //Then change your DocumentCompleted method to look like this:
    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {

        if (DocumentHasLoaded == false)  // I prefer using a ! before the variable instead
        {
            DocumentHasLoaded = true;    // You will have to create your own appropriately timed mechanism to reset this variable's state should you want to execute the whole process again.
            div_result = webBrowser1.Document.GetElementById("div_result");
            div_result.AttachEventHandler("onpropertychange", new EventHandler(resultEventHandler));
        }
    }
}

In order to answer your second question I require more information about the data that is loaded in the DIV; e.g. where it comes from and what type it is plus any other pertinent information you can think of.

Jamie
  • 1
  • 2
  • "I prefer using a ! before the variable instead" so why do anything else? - it's your answer – weston Jan 13 '15 at 14:28
  • This analysis makes sense if the button click causes a page refresh. But, if the button click triggers some (client side) javascript from the page, where that JS alters the "div_result" element, then the C# event handler for onpropertychange **should** be triggered, shouldn't it? FWIW I have a similar case where the C# event handler used to get called, but now it does not. I currently suspect a change of behavior in MSIE due to a Windows Update. See [also](https://stackoverflow.com/questions/9184856/event-handler-for-webbrowser-control-onpropertychange-events-sender-and-e-obje) – shaun Dec 14 '20 at 19:00