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.
Related
I'm not quite sure how to ask this question. So I'm attaching two images
How can I expand the Product Details tab so that the html rendered in the webview2 control looks like the second picture using code behind?
You can inject script into a page using CoreWebView2.ExecuteScriptAsync that will find that element and perform a click on it. However, this will be a fragile solution since if the layout of the page or names of elements on the page change your script may no longer work.
I would recommend opening the desired page in the Edge browser, opening DevTools, Console, and trying out different script to click on the correct element. For example document.getElementById("product-section-overview").children[0].children[0].click() might work but depends on the ID of that element not changing, and the structure and order of its children.
Once you have the script you want you can inject it into the document via
await myWebView2.CoreWebView2.ExecuteScriptAsync("document.getElementById("product-section-overview").children[0].children[0].click()");
If you are interested in a library for use with WebView2 that provides a DOM API and automation functionality then you can try WebView2.DevTools.Dom. It's free for anyone to use.
// Add using WebView2.DevTools.Dom; to access the CreateDevToolsContextAsync extension method
// Only a single WebView2DevToolsContext should exist at any given time, when you are finished them make sure you dispose via DisposeAsync. The WebView2DevToolsContext can be reused if required
await using var devToolsContext = await webView.CoreWebView2.CreateDevToolsContextAsync();
// Get element by Id
// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var element = await devToolsContext.QuerySelectorAsync<HtmlElement>("#myElementId");
// Click The element
// This will simulate a mouse move then click
await element.ClickAsync();
More details and examples in the Readme
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.
Try to code with WPF. Currently I want to implement a simple webBrowser, and now I'm stuck. I want to get name of opened page (Every tab has name according to opened page), but I can't find the solution. In C# I can use this code:
TabControl.SelectedTab.Text = webBrowser.Url.Host.ToString();
But with WPF it doesn't work.
What is solution to find page name with WPF?
Please try like this,
TabControl.SelectedTab.Text = webBrowser1.Url.AbsoluteUri;
I am using Web Browser control in my project and i open a web that have file chooser object.
Now i want to inject programmatically a path to a file in this file chooser object .
I tried to get the HtmlElement ,but i not found in the source code the element Id.
Edit:
In the web there is "Browse..." button that open a file chooser,and then the file path is show in little text filed, and i want to inject the file path my self to the text field.
First.
establish a name, id or class for the element you want to change the value of. There are a number of ways of doing this. I would use firebug for firefox, or IE developer toolbar, or just view the source of the page and establish what the name/Id of the field is. Now if that field does not have a Name or an ID that you can use you might be able to get the containing element and iterate through the Child elements n times until you get the element you want.
For my embedded browser app I did the following in c#:-
// webBrowser is the name of the embedded IE browser in your app
var htmlDocument = webBrowser.Document;
if(htmlDocment!=null)
{
var field = htmlDocument.GetElementById("...the id...");
if(field!=null)
{
field.SetAttribute("value","...yourfilenamepathonyourmachine...");
}
// Now you would need to establish the ID of the submit element and click that
var submitButton = htmlDocument.GetElementById("...submit button...");
if(submitButton!=null)
{
submitButton.InvokeMember("Click");
}
// your code to loop?
}
So do you have the HTML of the page in question? that might help and a better answer can be given
Regards Julian
For the last two weeks I have been kind of stuck on a problem.
I am developing some web scrapers using C# and I am using a WinForms WebBrowser control in my application. I am able to fill up the web form which is opened in my browser and submit it automatically by using the following code:
HtmlElement submitButton = document.GetElementById("Element_ID″);
submitButton.InvokeMember(“click”);
So far everything is fine, but the problem is that there is one another element in the web form that I want to click too, but this element does not have any id or name so I don't know how to click this one.
Please help me as soon as possible I need it for my master thesis.
(I want to click the next page arrow button in the give website:
http://www.gelbeseiten.de/yp/11//subscriberlist_pageAction.yp?sessionDataString=H4sIAAAAAAAAAI2PQU8CMRCFfw0XSEmns9128k5KongwGjFeSZftIqILbhcVf70NSgg3X-pbyXjLfvCFpqsbbIMpwbVRRuaBELKm6iew5T4gLFUpdmKpewJAGD8xV7JaxalfpdZX6mP31bH4WQfZblJehXcd2tGvr0WwbunVIKbYIZjjKmoa3atct4RSh-pA/S912oY4qhWzyjJkLvPZV4P4JetNFHYWOG2OoCH4pZlyU-pjWdhjS/LY2sp7-p1lLCLOGXwTLqpT1XSqOiXcpE3Xzw-pncUtGSDNp0ZZwR0we92TxSHjIX0x-pIQM-p0AZuciLl7M/kGE-pmcGjIOsvEpTB-pADJS0suGAQAA&page=0&filterTrade=-&filterFunction=-&sortBy=sort_trade&availableLetters=ABCDEFGHIJKLMNOPQRSTUVW )
I've written many web-scrapers in the past using embedded WebBrowsers, so you've come to the right place.
When the element does not have a name you need to find it by either content, or another associated element that is named.
In the first instance we wrote helper methods to iterate the hierachy looking for a specific piece of content within an element.
For the second option you get the named element and use a specific index for the desired child.
A combination of both (find a specific parent then look for a child with the right content)
In your specific example webpage, the next page anchor has a class type of "arrow next" you can search for.
You could do
HtmlElement next_arrow = document.GetElementsByTagName("a")
.Cast<HtmlElement>()
.Where(e => e.GetAttribute("class") == "arrow next")
.FirstOrDefault();
if (next_arrow != null)
{
next_arrow.InvokeMember("click");
}
Here's a trick, not by InvokeMember("click") rather just "simulating the click" -
this is the link for the first page:
gelbeseiten.de/yp/11//subscriberlist_pageAction.yp?sessionDataString=H4sIAAAAAAAAAI2PQU8CMRCFfw0XSEmns9128k5KongwGjFeSZftIqILbhcVf70NSgg3X-pbyXjLfvCFpqsbbIMpwbVRRuaBELKm6iew5T4gLFUpdmKpewJAGD8xV7JaxalfpdZX6mP31bH4WQfZblJehXcd2tGvr0WwbunVIKbYIZjjKmoa3atct4RSh-pA/S912oY4qhWzyjJkLvPZV4P4JetNFHYWOG2OoCH4pZlyU-pjWdhjS/LY2sp7-p1lLCLOGXwTLqpT1XSqOiXcpE3Xzw-pncUtGSDNp0ZZwR0we92TxSHjIX0x-pIQM-p0AZuciLl7M/kGE-pmcGjIOsvEpTB-pADJS0suGAQAA&page=0&filterTrade=-&filterFunction=-&sortBy=sort_trade&availableLetters=ABCDEFGHIJKLMNOPQRSTUVW
as you see page=0; clicking next, gives the link -
gelbeseiten.de/yp/11//subscriberlist_pageAction.yp?sessionDataString=H4sIAAAAAAAAAI2PQU/DMAyFf00vmzLFdprE8gkmwTggEENcp3RNxxh0o-pmA8euJBlO1G0-p-pvCf58zNwUzW-pDKyQalSmckExl6DqJpKnPCEuVbDaYFUvBcEIFXgVu1Ws2nV6Xac-pZn89X5xFwoed2MvQbmI73rf1eL4L3SakFFsJOBpnzcJbte9W4hSI-pQ/S912oY4qhWz5LDSC992Dl/QR60ahPki2OZKeNfCgiba18oicmLV8lTcoS8t6BJ8zsHMo3yEU1VE1D1ZmWm7Tt-psXxtNwCMmjS4BhJ7oDAy72WR5CH/MT0l1HQEVa46QDK2Z/JsTyhcdIAWrZeGy8/k7LJ5YQBAAA-e&page=1&filterTrade=-&filterFunction=-&sortBy=sort_trade&availableLetters=ABCDEFGHIJKLMNOPQRSTUVW
now page=1
and so on... in general clicking next means page=(x+1) clicking prev means page=(x-1). so build a string according the requirements. this addresses ur problem, however there are some other data also sent with querystring, that u have to append to the string as well.