I'm trying to automate in a WinForm using a WebBrowser control to navigate and pull report info from a website. You can enter values in textboxes and invoke the click events for buttons and links, but I have not figured out how select a option drop-down .... in a automated way. Anybody recommend how to select a item from a drop-down, given this html example:
<SELECT id="term_id" size="1" name="p_term_in"><option value="">Select Another Term<option value="201050">Summer 2010<option value="201010">Spring 2010<option value="200980">Fall 2009</SELECT>
For others that can learn from entering values to textboxes and invoking click events here's how you do it:
webBrowser1.Document.GetElementById("<HTML ELEMENT NAME>").SetAttribute("value", "THE NAME");
Invoke button or hyperlink click:
webBrowser1.Document.GetElementById("<BUTTON>").InvokeMember("click");
So I've solved entering values and invoking click, but I have not solved selecting a drop-down value.
Assuming you have the following select in the HTML:
<select id="term_id" size="1" name="p_term_in">
<option value="">Select Another Term
<option value="201050">Summer 2010
<option value="201010">Spring 2010
<option value="200980">Fall 2009
</select>
This should allow you to preselect the third value:
webBrowser1.Document.GetElementById("term_id").SetAttribute("value", "201010");
var select = webBrowser.Document.GetElementById("ddlProyectos");
mshtml.HTMLSelectElement cbProyectos = select.DomElement as mshtml.HTMLSelectElement;
var total = cbProyectos.length;
for (var i= 0; i < total; i++)
{
cbProyectos.selectedIndex = i;
if (cbProyectos.value.Contains("13963"))
{
break;
}
}
//cbProyectos.selectedIndex = 4;
select.InvokeMember("onchange");
select.Children[4].SetAttribute("selected", "selected");
var theElementCollection = webBrowser.Document.GetElementsByTagName("select");
foreach (HtmlElement el in theElementCollection)
{
if (el.GetAttribute("value").Equals("13963"))
{
el.SetAttribute("selected", "selected");
//el.InvokeMember("click");
}
}
You will have to select the selected attribute on the option you want.
Given:
<select id="mySelect">
<option>1</option>
<option>2</option>
<option>3</option>
</select>
The following would selct the third option:
webBrowser1.Document
.GetElementById("")
.Children.GetElementsByName("option")[2]
.SetAttribute("selected", "selected");
try this:
add reference to microsoft.mshtml in project --> add reference...
Dim cboTemp As mshtml.HTMLSelectElement
cboTemp = WebBrowser1.Document.GetElementById("myselect").DomElement
cbotemp.selectedindex = 2
having the variable cbotemp set to a select element gives you greater access to the control :)
HtmlElement hField = webBrowser1.Document.GetElementById("ID");
hField.SetAttribute("selectedIndex", "2");
select by index (zero based) not the value....
I'm answering on this post after five years, for the people who are searching a solution of this problem.
If you just need to submit/post a value for the dropdown then this line is sufficient:
webBrowser1.Document.GetElementById("term_id").SetAttribute("value", "200980");
But if you really need to select an underlying OPTION, then:
HtmlElement selectDom = webBrowser1.Document.GetElementById("term_id");
foreach (HtmlElement option in selectDom.GetElementsByTagName("option"))
{
if (option.GetAttribute("value") == "200980")
{
var dom = option.DomElement as dynamic;
dom.selected = true;
// selectDom.InvokeMember("onChange"); // if you need this too
break;
}
}
You can use this:
webBrowser1.Document.GetElementById("term_id").SetAttribute("value",yourText);
Related
I'm having some trouble using Object Identification on a drop down list, what is being returned is this:
IListBox pricerBox= browser.Describe<IListBox>(new
ListBoxDescription
{
TagName = #"SELECT",
Name = #"select"
});
I would like to select a value from the drop down list and I tried using this as an example: How to select an option from drop down using Selenium WebDriver C#? But didn't have any luck as I'm using LeanFT in C# MS VS.
When inspecting in Chrome, this is the list box element details:
<select tabindex="1" style="width: 150px;">
<option value="3">Mc1</option><option value="11">Mc2</option><option
value="17">Mc3</option><option value="21">Mc4</option><option
value="57">Mc5</option></select>
This is what I coded so far:
//pricer box
IListBox pricerBox= browser.Describe<IListBox>(new
ListBoxDescription
{
TagName = #"SELECT",
Name = #"select"
});
Thread.Sleep(3000);
pricerBox.Click();
Please have a look at LeanFT's documentation for IListBox, the Select function looks like what you're looking for.
pricerBox.Select("Mc3"); // No need to sleep before this
I am adding some values to a drop down list using a loop:
for (Int32 i = 1; i <= MaxOrderQuantity; i++)
{
myDropDownList.Items.Add(new ListItem(Convert.ToString(i), Convert.ToString(i)));
}
I want to add a CSS attribute to the new ListItem at the same time. I have seen I can use
.Attributes.Add("class","foo")
However the only way I can find to do it is by breaking down my single line of code in to 3 separate lines of code like this:
ListItem newListItem = new ListItem("my value", "my value");
newListItem.Attributes.Add("class", "blah");
myDropDownList.Items.Add(newListItem);
The intellisense allowed me to write the following code but it errors and says "The best overloaded method match for 'System.Web.UI.WebControls.ListItemCollection.Add(string)' has some invalid arguments.
myDropDownList.Items.Add(new ListItem(Convert.ToString(i), Convert.ToString(i)).Attributes.Add("class","blah"));
How is it possible to add a new ListItem with a 'class' attribute in a single line of code?
You cannot do that, because Attributes.Add() does not return a ListItem object.
See documentation: https://learn.microsoft.com/en-us/dotnet/api/system.web.ui.attributecollection.add?view=netframework-4.7.2#System_Web_UI_AttributeCollection_Add_System_String_System_String_
You can either use the old way
ListItem newListItem = new ListItem("my value", "my value");
newListItem.Attributes.Add("class", "blah");
myDropDownList.Items.Add(newListItem);
or rewrite your version of Add().
I recommend adding the css to myDropdownList and then let CSS do the selecting of the items within the list. This is how CSS is designed to work.
// this Markup
<asp:DropDownList ID="myDropdownList " runat="server">
</asp:DropDownList>
// can have a CSS class added on the server like this
this.myDropdownList.Css = "blah";
myDropdownList.Datasource = data;
myDropdownList.DataBind();
// which will render on the page like this
<select class="blah" id="myDropdownList">
<option>Foobar 1</option>
<option>Foobar 2</option>
<option>Foobar 3</option>
</select>
// which you can apply CSS styling to like this
select.blah option {
flont-size:large;
color: #aaa;
font-type:italics;
}
I'm using WebForms. In my Form, I have a dropdownlist control. Sometimes the Select option gets added twice in my from. How can remove this duplicate option or hide it?
I've tried to count how many times Select option is added then hide it but wasn't successful.
The reason why it's adding it twice is because grdview_Color_DataBound gets called twice.
<select name="ctl00$MainContent$grdview_Color$ctl10$ddl_Grd_Color" id="MainContent_grd_ddl_grdview_Color" class="form-control dropdown">
<option value="0" selected="selected" disabled="disabled">Select</option>
<option value="0" disabled="disabled">Select</option>
<option value="Yellow">Yellow</option>
<option value="Red">Red</option>
<option value="Blue">Blue</option>
<option value="Green">Green</option>
</select>
protected void grdview_Color_DataBound(object sender, EventArgs e)
{
ListItem firstItem = new ListItem("Select", "0");
firstItem.Attributes.Add("disabled", "disabled");
ddl.DataSource = dataSource;
ddl.DataTextField = TextField;
ddl.DataValueField = ValueField;
ddl.DataBind();
ddl.Items.Insert(0, firstItem);
}
A naive way would be to store the items in the drop down list in some kind of container like a list. Clear the drop down items and then loop through your container, only adding unique items back to the drop down items list with something like:
// Save the items
savedItems = dropDownItems.Items;
// Clear The items
dropDownItems.Items.Clear();
// Go through the container adding unique items to the drop down list
foreach (string item in savedItems){
if (!dropDownItems.Items.Contains(item)) {
dropDownItems.Items.Add(item);
}
}
of course this way is not the best way, but it is a way if you are in a hurry.
You need to set the AppendDataBoundItems property to true to preserve the existing values in the DDL. You also need to ensure that you are not doing it on every postback - your code sample does not show if and how you are doing this in the Page_Load() method.
I want a solution for writing a script for C# Automation using selenium web driver library in TFS, I have to store all disabled values and then click on them. Actually, the validation is like that I should not be able to click on disabled values in a drop-down list. So I need help here in 2 things:
I want to store disabled values first and then
I want to iterate through them
To write a boolean/any function for validation that I am unable to click that values
Here is the code:
<select name="ctl00" onchange="javascript:setTimeout('__doPostBack(\'ctl00$ctl00$\',\'\')', 0)" id="ctl00_ctl00_" style="width:200px;">
<option value="1" disabled="disabled">A</option>
<option selected="selected" value="2" enabled="enabled">B</option>
<option value="3" disabled="disabled">C</option>
<option value="4" disabled="disabled">D</option>
</select>
So, A, C, and D are the options for which I want validation.
Need a helping hand :)
Thanks in Advance
I use something like this to search my pages for 'is-loading' classes to check for loading elements. I've reflavored to check for 'disabled' classes, pass them into an array, and then click on the. Not tested but hopefully gets you pointed in the right direction.
new WebDriverWait(driver, MyDefaultTimeout)
.Until(e => ((IJavaScriptExecutor)e)
.ExecuteScript(""+
"do {"+
// Find loading element(s)
"var element = document.getElementsByClassName('disabled');"+
// Create array of elements
"var elementList = Array.prototype.slice.call(element);"+
"if(!elementList === undefined && !elementList == 0) {"+
// Map Id and Attribute
"var array = elementList.map(function(v){ return {'ID': v.id} });"+ //"'Attr': v.getAttribute('data-custAtt')"+
// Output array of disabled objects
"console.log(array);"+
// Check to see if array is empty
"if (!array === undefined && !array.length == 0) {"+
// Click disabled element
"var i;"+
"for (i=0;i<array.length;i++){"+
"var disabledElement = array[i];"+
"disabledElement.click();}";"+
"}"+
"else"+ // Array is empty, exit the loop
"{"+
"done = true;"+
"}"+
"}"+
"else"+
"{"+
// We may not have an array of elements
// So if we only have 1
"if(!element === undefined) {"+
// Click disabled element
"element.click();"+
"}"+
"else"+
"{"+
"done = true;"+
"}"+
"}"+
"}"+
"while(done = 'false');")
.Equals("complete"));
I have a form that automates tasks on a page by user input but I'm having trouble interacting with an element on the page. It's a CheckBoxList with dynamic names and number of elements. The HTML looks like this:
<ol id="ratingModification_SupplierContact_content">
<label><input type="checkbox" name="searchQuery.vehicleGroups[0].isSelected" value="on" class="vehGrp"> abcd ef (ghi)</label> <br>
<label><input type="checkbox" name="searchQuery.vehicleGroups[1].isSelected" value="on" class="vehGrp"> jklm no (pqr)</label> <br>
</ol>
Where " abcd ef (ghi)" is the label of the first checkbox.
I already have a button that extracts the labels from the elements and puts them in an array designed with help from users here:
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
var vehicleGroupNames = vehicleGroupInputElements.Select(f => f.FindElement(By.XPath(".."))).Select(f => f.Text).ToArray();
And I populate my form's CheckedListBox with:
vehicleGroupList.Items.AddRange(vehicleGroupNames);
But when I try to send the user selection back to the page I run into issues. I have tried selecting based on index via IndexOf() and the ClassName but can't figure out the syntax to make it work. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
var checkTarget = Builder.Driver.FindElements(By.ClassName("vehGrp"));
checkTarget.IndexOf(checkIndex).Click();
}
Which won't compile because int checkIndex cant convert to an IWebElement. I have also tried to build a string to address the index with xpath but it can't find the element or throws a no compound names exception. Failed example:
foreach (int userChecks in vehicleGroupList.CheckedItems)
{
int checkIndex = vehicleGroupList.Items.IndexOf(userChecks);
string elementTarget = "searchQuery.vehicleGroups[" + checkIndex + "].isSelected";
var checkTarget = Builder.Driver.FindElements(By.XPath(string.Format("//option[contains(text(), {0}]", elementTarget))).Click();
}
I've also tried to find the element by label via xpath similar to the above but it never finds it. What is the correct way to find the elements and check them?
When you want to click on each checkbox you can use :
var vehicleGroupInputElements = Builder.Driver.FindElements(By.ClassName("vehGrp"));
foreach (IWebElement checkbox in vehicleGroupInputElements)
{
checkbox.Click();
}
Just looked into Xpath syntax and found the answer. With the help of Chrome's 'copy Xpath' function in inspect mode, I found the path needed and successfully clicked the input element.
Example Xpath of the first input is as follows (notice the HTML for label[index] is 1 more than the way C# would count.)
//*[#id="ratingModification_SupplierContact_content"]/label[1]/input
And solution as follows
//Retrieves the checked items from the form and sends them to the page.
foreach (object checkedItem in vehicleGroupList.CheckedItems)
{
//Gets the index of the checked items.
int checkedIndex = vehicleGroupList.Items.IndexOf(checkedItem);
//Adds 1 to the index to match format of the page HTML.
checkedIndex++;
//Puts the index+1 into a string.
string indexText = checkedIndex.ToString();
//Finds the element by index+1.
var clickTarget = Builder.Driver.FindElement(By.XPath(string.Format("//*[#id='ratingModification_SupplierContact_content']/label[" +indexText+ "]/input")));
clickTarget.Click();