Unable to access a generated DOM from a WPF WebBrowser - c#

I need to host a web page inside a WPF application, so I added a WPF WebBrowser control as follows...
<WebBrowser Name="WebBrowser" />
In the C#, I did the following...
WebBrowser.Navigate("http://tableau.visionrt.com/#/signin");
WebBrowser.LoadCompleted += PageLoadedLogin;
...and had the following method, in which I wanted to fill in the two inputs and submit the form...
private void PageLoadedLogin(object sender, NavigationEventArgs e) {
IHTMLDocument3 doc = (IHTMLDocument3)WebBrowser.Document;
HTMLInputElement u = (HTMLInputElement)doc.getElementById("username");
HTMLInputElement p = (HTMLInputElement)doc.getElementById("password");
}
However, both u and p are null, meaning I can't access the elements. I can see the elements if I view the source in a a browser, but I can't access them in code.
I tried the following, just in case I'd got the names wrong...
IHTMLElementCollection inputs = doc.getElementsByTagName("input");
...but that didn't find anything.
Now, looking at the actual HTML that the URL returns, it looks like the <input> and <button> elements are generated in JavaScript, in which case they may not have been created when the LoadCompleted event fires.
So, I tried adding a call to Thread.Sleep in a quick-and-dirty way of making sure the JavaScript had had time to create the elements, but it didn't make any difference.
I tried using the HtmlAgilityPack as suggested in this post, but that gave the same lack of results as above.
Anyone any ideas why I can't access generated elements? All of this works fine on a page with static HTML.

Related

Stop multiple WebBrowsers from starting yt-videos?

I'm working with a winform TabControl showing WebBrowsercontrols to display youtube videos.
However with two videos or more it becomes really annoying as all videos start directly.
I basically need to find out if there is a JS function, html code or a simple WebBrowser property to change, so videos are paused.
It might come in handy to find something like that for video quality too.
Has anybody ever heard of/seen where this option is stored? Or maybe the Js function itself being invoked when manually setting the quality?
EDIT:
b.DocumentCompleted += delegate { b.DocumentText=b.DocumentText.Insert(b.DocumentText.IndexOf("class=\"video-stream html5-main-video\""), "autoplay=false ");};
b.Url = new System.Uri(inp[s], System.UriKind.Absolute);
Basically this should add a new Event handler on each webbrowser form that modifies the DocumentText when the Uri that is called during creation has loaded.
Even though the browser debugger shows
<video tabindex="-1" class="video-stream html5-main-video" controlslist="nodownload" style=... src=...></video>
this isn't in the actual source code.
However I found
$oa=function(a){g.S(a.o,"video-stream");g.S(a.o,"html5-main-video");var b=a.app.g;b.zc&&a.o.setAttribute("data-no-fullscreen",!0);b.Oh&&(a.o.setAttribute("webkit-playsinline",""),a.o.setAttribute("playsinline",""));b.Nr&&a.o&&a.P(a.o,"click",a.o.play,a.o)};
in the base.js. Is it possible that youtube generates the html from the js?
How can I modify the video-tag attributes then?
I tried to modify when the event handler manipulates the video tag, since there may be DocumentCompleted events thrown from scripts or anything.
delegate (object sender, System.Windows.Forms.WebBrowserDocumentCompletedEventArgs e){
if (e.Url.AbsolutePath != ((System.Windows.Forms.WebBrowser)sender).Url.AbsolutePath){
//...
However it still fails as there is no occurance of the specific class that on the video tag.
I now dodged this by loading the Url only when the browser tab is selected, if someone finds a real solution, feel free to share

GeckoInputElement.Click returns System.NullReferenceException

I am making use of the GeckoWebbrowser control in a C# Windows forms app environment.
I am wanting to call the click event on a button on the browser page, from a code event behind.
When I try an access a specific button I can find it by making use of the GetElementById command, however after assigning this information to the GeckoInputElement to call the click event, there is a null reference exception visible with this.
My code call to get the element looks like this:
GeckoInputElement betbt = new GeckoInputElement(wBrowser.Document.GetElementById("bet-bt").DomObject);
If I assign it like this I can access the element but still cannot click it with the GeckoElement object:
GeckoElement g1 = (GeckoElement)wBrowser.Document.GetElementById("bet-bt");
The HTML for the button looks as follows:
<button data-action="bet" id="bet-bt" class="action">Bet</button>
GeckoInputElement's are for Html Input elements.
Just use GeckoHtmlElement:
GeckoHtmlElement g1 = (GeckoHtmlElement)wBrowser.Document.GetElementById("bet-bt");
GeckoElement and GeckoHtmlElement exist to differentiate when the browser is displaying non html.
For Html documents always use GeckoHtmlElement.

C# WebBrowser different html document after navigate

I have a really strange problem in C#:
First I use the WebBrowser control and the navigate method to browse.
wb_email.Navigate("https://registrierung.web.de");
Now I can change the innerText of htmlelements without any problems.
wb_email.Document.GetElementById("id4").InnerText = "Alexander";
But when I reload the page by simply using the navigate method with the same url again,
I get a null exception. It seems as he can't find the element.
So I used an inspector for Firefox to see if the htmlelement really changed, after reloading.
But only the url is changing, htmlelements are all the same.
What I'm doing wrong?
You're just changing the DOM in the displayed page. When you reload the page, the WebBrowser instance will just refresh the DOM from the server again and lose your changes.
The WebBrowser class isn't designed for editing rendered pages inside itself, as it's basically just a wrapper to an embedded Internet Explorer instance.
Make sure the website has finished loading before accessing any element. Like:
webBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Access elements here
}

Problems when assigning values via JavaScript to Asp.net labels and then passing via C# session object

I am assigning variables to asp labels via javascript with a simple innerHTML call
example:
document.getElementById('labelName').innerHTML = parseFloat(var).toFixed(2);
It appears in the label fine, and I am able to continue to manipulate it via javascript.
I then set it up so that that variable is put into a session object via C# codebehind buttonClick event.
example:
protected void btnConfirm_Click ( object sender, EventArgs e )
{
Session["sessionName"] = labelName.Text;
}
The buttonConfirm_Click method fires it Response.Redirects to another page and populates asp labels with the session object via the c# codebehind page_load method.
example:
lblResult.Text = Session["sessionName"].ToString();
When doing this, the label is empty, no errors or 'null'. I have tried to narrow down the issue by trying various things. When I assign the text explicitly in the c# code behind of the first page and the recieve and assign it to the label on the next page, it shows correctly.
example:
Page 1:
Session["sessionName"].ToString() = "Test";
Page 2:
lblResult.Test = Session["sessionResult"].ToString();
I have tried several other things, such as casting the variables in javascript and in the codebehind, and checking to make sure I had runat="server" within each applicable label.
Anyways, is there something here I am missing? Is asp.net unable to detect the changes that javascript has made to the labels? Are there some incompatibility issues when using innerHTML or anything like this that maybe be causing such a thing to occur?
Thanks in advance!
The problem is that the text in a span tag (that is what asp:Label will render) isn't sent in the post to the server and therefore you can't read your changes server side. You'll need to use a input element (hidden field, textbox etc depending on what your ui should look like).

Page Title from a User Control possible?

I have a Search.aspx page which calls UCSearch control. UCSearch control does everything like getting what is being searched and what should be displayed, etc. I am trying to give the title to the page. As i dont have any info to write the code in the aspx page, i am thinking to write it in the control. But it is not displaying me when i tried using Page.Title in control. What am i doing wrong?? This is in Asp.net and C#.
Page.Title = "Search Results for Newark, NY";
Thanks in advance!!
Does not:
this.Page.Title = "My beautiful title";
work?
You should be able to get to the ASPX using the Parent property of the control. Cast that property to a Page (it's a WebControl or something similarly generic), then set its Title property. If you have a hierarchy of master pages or are nesting this control in other controls, you may need to traverse the Parent hierarchy for a few more levels.
You could also fire an event from your user control, passing the Title that you would like to display. You could then handle this event on the page, and set the title.
This does require a small amount of code in your aspx page, however, at least now the user control does not care where the title goes, the parent of the control can worry about it. If ever you want to change where this title goes, or even put it in multiple places, you don't have to change the user control. Let me know if you want a sample, I'll add it.
If you don't like that idea, then cederlof's answer will work, I just tested it.
protected void helloBtn_Click(object sender, EventArgs e)
{
this.Page.Title = "hello from control";
}
** You can use naming container to find the parent control of the current control. Through this way you can move through the page hierarchy.
Quickwatch will help you a lot in figuring out the things and building the statement for quick casting. Do some more research on naming container.
var container = userControl.NamingContainer;
if(container is Page)
{
Page p = container as Page;
p.Title = "Your Title";
}
**
Above is not the exact solution, but can help you it you can usercontrol directly on the page. Unless you need to iterate through the page controls. This was just for an quick help.

Categories