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.
Related
I have a query in windows. forms I am new to this.
I have developed a form where users can open any website from it and upon right click of any element I am displaying the element name, id, and few attribute values in a data grid. For this, I have used webbrowser control.
However, I was facing some errors for a few of the sites so I tried to move to webview2. But here comes the issue
Earlier I used to get the element using the below code
HtmlElement element = webbrowser1.Document.GetElementFromPoint(e.ClientMousePosition);
But now I am unable to retrieve an element by using webview2.
Can someone please help me with this?
You will need to use JavaScript. You will need async methods.
Then, you can get the element by passing a javeScript string.
Point p = e.ClientMousePosition;
string jElement = await webBrowser1.ExecuteScriptAsync($"document.elementFromPoint({p.X},{p.Y})");
The result is JSON. You will need to parse the result to get the element name.
I am trying to figure out the same thing.
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.
I am trying to access a radio button. From my research I found the element using the name, since the elements of a radio button have the same name. I want to select the second button, but I get an element not visible exception and the location property of the element returned is outside the window. However, I can see the element on the page.
The exception: An exception of type 'OpenQA.Selenium.ElementNotVisibleException' occurred in WebDriver.dll but was not handled in user code
ReadOnlyCollection<IWebElement> webElements = webElement.FindElements(By.Name("thename"));
webElements[1].SendKeys(Keys.Return);
I tried to move to location using the execute javascript as well as the Actions method. Neither worked.
I tried all possible keys to send to click for the Actions method:
Actions actions = new Actions(webDriver);
actions.MoveToElement(webElements[1]);
actions.SendKeys(Keys.Return);
actions.SendKeys(Keys.Enter);
actions.SendKeys(Keys.ArrowDown);
actions.Click();
actions.Perform();
For the javascript executor I tried two methods. To scroll into view, and to scroll by the amount that the Location property of webElement[1] told me it was off by.
IJavaScriptExecutor js = webDriver as IJavaScriptExecutor;
string title = (string)js.ExecuteScript("arguments[0].scrollIntoView(true);", webElements[1]);
string title1 = (string)js.ExecuteScript("javascript:window.scrollBy(557329,136);");
I still keep getting the location not visible exception.
A quick check you could do is open the developer tools in browser and in the console see if document.querySelector("[name='thename']") finds the element. If not, maybe that element is in an iframe or the name you are using may have a typo. You will also want to make sure that the radio button you are trying to access is below 'webElement' in the DOM tree. It's also possible that the page is still loading when you are checking for the element. To check for this put in a wait before trying to find the element so the page can load fully.
I am using Webview to displays an html page that contains 2 inputs of type text and a submit button.I want the app user to be able to fill these fields on the app before launching the webview.Therefore taking the user directly to the result of the search.
Apparently the webview.Document is no longer available.
Any suggestion ?
Once the HTML is loaded into WebView, you can call a method called InvokeScriptAsync through which you can invoke some kind of Javascript.
await myWebView.InvokeScriptAsync("eval", new string[] { "var elem = document.forms[0].submit();"});
This way you can fill the input field, click a button or whatever you need.
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).