I use WebBrowser.Document.DomDocument and found that it has different DOM model that I can see in IE Debug Tool.
IE Debug Tool contains the valid actual DOM model while WebBrowser.Document.DomDocument doesn't contain some elements added dynamically by JavaScript.
Actually the WebBrowser control displays all elements, even those that were added dynamically, but WebBrowser.Document.DomDocument contains outdated DOM model.
IE Debug Tool can display the actual modified DOM model at it's current state, how to get the current DOM model using WebBrowser component?
There definitively should be a way to do it.
This question could use better documentation. But this is a pretty classic problem, it is a timing issue. You no doubt access the DomDocument property too early, typically you'd do so in the browser's DocumentCompleted event. That's roughly the time the javascript code starts executing. So you'll get the version of the DOM before the changes made by the script.
There's no decent way to deal with the problem. Execution of Javascript is entirely asynchronous and there are no events to indicate any scripting code started or stopped running. The only decent thing you can do is "wait a while", use a timer. Preferably repeatedly until you see a good indication from the DOM that the script is done making its changes.
Related
I tried WebBrowser but any solution related to WebBrowser I find uses the exact same codes, WebBrowser.DrawToBitmap
Problem with that is, it gives out inaccurate results depending on URL, to what page actually would look like, sometimes even blank pages.
So I am looking for any alternate solution to WebBrowser if there is any.
It needs to run in background, as in not open any browser on screen, render it in background with all scripts and get an image.
If I understand what you're trying to do, you might be interested in a framework called PhantomJS, which is a WebKit "browser" engine which runs the pages without visually rendering them. It can be used to capture screens.
Now this technique requires JavaScript, but there is something called Selenium WebDriver to help you wrapping that. Users here at SO posted a simple example and this comment looks useful as it contains the list of required Packages.
So I've been trying to use something other than IE for my webcontrol in a side-project of mine (C#, WPF project type) and I was looking around for alternatives and have tried in the past but failed to implement them.
I decided to try again and implement awesomium, however it is still confusing as always and doesn't have any straight forward examples for me to use as a base.
Would someone be able to show me how to implement awesomium for a webview/webcontrol? My vision is to have it navigate to a shoutbox website, and while my application is still open to keep it there (i.e not refresh it so that it doesn't lose anything) as it is being shown in the space of tabitem.
I have used Awesomium, but the last version I used was 1.6.1, and there are some differences between that and the current version - they've actually made things easier.
The documentation says that you should be able to force navigation of the control simply by setting the Source property:
<osm:WebControl Name="webControl"
Source="http://www.google.com/"
/>
If you find the Source property is not bindable then simply revert to using some code behind in the view - subscribe to a property change event from the viewmodel (or from an event broker if you are using one), and change the Source property in response to an event.
I believe, the problem with the Source property is that if you are setting it to the same URI to refresh, it won't refresh because of a bug. It is documented on their github page and their answers page.
As workaround, to refresh your page correctly you need to pass a fake URI first and then your page again to your binding property, like this:
CurrentSource = "FakeUriString".ToUri();
CurrentSource = "http://www.yourpage.com".ToUri();
Keep in mind, my current version of Awesomium is 1.7.4.2 and they may fix this issue in the future as they stated in their issues page.
We are trying to develop a game using XNA. We decided to use Awesomium for GUI, because it is easy to use and its extremely powerful. However we found a weird problem:
After hover over any form elements (like input, buttons, input etc) we noticed a massive FPS drop to like 2 fps. On the other hand when we hover over text elements (p, div, a etc) nothings happen and everything is working as it is suppose to (we have over 400 FPS). We found out that problem is with isDirty function (Awesomium::WebView), because is always true (when mouse is over form element). I don't know if it can be a reason, but onMouseOut function is never called.
Does anybody have similar problem? What can we do about that?
Greeting, Valker
I've used Awesomium in a Unity 3D project and didn't have any problem like that.
You should check the onmouseover event handler.
If you've done your homework you should be able to load the assets from the webpage.
So load the page directly in chrome and use console.log('on-mouse-over') to have a JS feedback when the event is called. If you are flooded with those console messages than the event handler is invoked way to often and you should first debug your JS in the browser. Only then load it up in your AWE client.
I'll share some more of my experience with Awesomium with you.
My recommendation is to keep the JS code as thin as possible and unload as much code as possible to C#. Here's the reason why.
You'll probably want to implement C# routines to check if the mouse is actually on an opaque spot (inside a WebView) or on a (semi-)transparent zone that should not prevent click-throughs to underlying objects. When you use CSS like box-shadow you'll soon notice that the shadow adds pixels around and inside the WebView boundary.
Those bordering pixels should be click-through. You may also have non-rectangular shapes or dynamic slide-down UI elements and similar. So you'll have to work your way around the fixed WebView boundaries by checking manually if you're on a transparent spot or not.
You also want C# code to handle drag&drop across multiple WebView instances because each has its own global context and there is no way to handle cross-WebView drag&drop in JS alone.
So you already have all this C# code implemented.
Just do another step and charge all UI processing off the WebView.
You should use JS just to send/receive messages from the C# code and complex JS scripts should be avoided.
The same functionality in C# is much easier to debug. And what emerges naturally is the MVC pattern, with controllers implemented in C#.
Very thin JS is less error prone.
And last but not least, if you are a paying customer you should take advantage of their customer-only support and forums.
Wish you luck especially with the drag&drop nightmare! :)
Or a way to detect it is finsihed rendering?
Actually almost exactly this question
Gridview, is there an event, how would I determine that it has finished being rendered?
but he does not state exactly how he detected that everything had been drawn/resized.
EDIT: (Adding my comment from below to specify what i am trying to do)
I am trying to create a work around for static header for a gridview by basically dynamically adding another gridview above the one that actually has the data in it. I resorted to this after trying about 12 different suggestions/solutions with no real luck. What i have works pretty well except that the new header is rendered before the one with the data in it completes its re-sizing, I realize what i am trying might not even work since it might require another postback to re-render the new one after i find the sizes of the column headers but thought i might get around that with an update panel.
I realize this might not be the most elegant solution but honestly have yet to find any solutions to this problem that come even close to elegant or have even worked correctly with current browsers.
It renders at the client so the server doesn't know what is happening there.
You are probably looking for the DataBound event.
Otherwise, at the client, you can determine when the page has finished loading (the jquery ready function) and then call back to the server. But I can't imagine anything useful you could do. If you send more data to the client and it renders again, you could have an infinite loop.
Everything in an ASP.Net webpage is rendered at the same consecutively at the same stage of the lifecycle (see http://msdn.microsoft.com/en-us/library/ms178472.aspx), so the Gridview will be rendered between Gridview_PreRenderComplete and Gridview_Unload.
You page PreRender will fire, then the control PreRender, then the page will call the Gridview Render method (there is no event for this) then the control Unload will fire and then the page Unload will fire.
Other posters to this question are referring to the client side rendering whereas I am referring to the server side rendering process. Which is it that you are actually after and why please?
I am using a WebBrowser control. I edit some HTML inputs and click a button in the WebBrowser DocumentCompleted event handler. My problem is clicking the button I mentioned changes the content of the Document using AJAX, Knowing that I need to parse some information from the new changes. The question is: How can I detect when the document has finished loading the new content. Is there any sort of an event handler like DocumentChanged.
Thanks in advance.
I figured you'd be back about this. The extensibility object model has no great support for observing scripting execution. It isn't practical, scripting code can run completely asynchronous from the page state at unpredictable times. If there are no reliable DOM modifications made by the script that you can read back then you have no great options beyond just spinning your wheels for a couple of seconds to give it 'enough time'. Shouldn't be a problem given that you run this in a worker thread, just use a System.Windows.Forms.Timer who's Tick event calls Application.ExitThread to end the thread.
No way to do that, I'm sure - WebBrowser control is very simple and poor-functional
Do you control the HTML of the document you're displaying ? If so, after the ajax changes have completed you can use Javascript to call a C# method in your parent form window.external.MyPublicMethodName() instead. Your app needs to be running in Full Trust for this to work, and also to have set the browser ObjectForScripting object to the form itself e.g. this.webBrowser1.ObjectForScripting = this; in your Form_Load event.