Programmatically select an item from a drop down in .NET Webbrowser Control - c#

Below is a html script, I grabbed from a website. I wanna select the item programmatically using .NET
<div id="MySite.condition_s-wrp" class="c-wrp-slctbx" style="z-index: 1;">
<input id="MySite.condition_s-input" type="text" autocomplete="off" readonly="readonly" tabindex="0" class=" c-slctbx-medium" style="width: 268px;">
<ul class="c-ul-slctbx max_height_300" style="width: 285px; display: none; top: 21px;">
<li id="MySite.condition_s-option-" class="c-li-slctbx">Please choose</li>
<li id="MySite.condition_s-option-First" class="c-li-slctbx">First</li>
<li id="MySite.condition_s-option-Second" class="c-li-slctbx">Second</li>
</ul>
<select id="MySite.condition_s" name="attributeMap[MySite.condition_s]" class=" c-slctbx-medium" style="display: none;">
<option value="">Please choose</option>
<option value="First">First</option>
<option value="Second">Second</option>
</select>
</div>
Please note the following code is not working at all.
webBrowser1.Document.GetElementById("MySite.condition_s").SetAttribute("value", "First");
Any quick help will be highly appreciated.

Finally I figure it out with one of my friends. This little function will do the rest very easily.
Thanks to Farrukh Momin and his time.
public void SetComboItem(string id, string value) {
HtmlElement ee = this.webBrowser1.Document.GetElementById(id);
foreach (HtmlElement item in ee.Children) {
if (item.OuterHtml.ToLower().IndexOf(value.ToLower()) >= 0) {
item.SetAttribute("selected", "selected");
item.InvokeMember("onChange");
}
else {
item.SetAttribute("selected", "");
}
}
ee = this.webBrowser1.Document.GetElementById(id + "-input");
ee.InnerText = value;
}
Calling Function
this.SetComboItem("MySite.condition_s", "First");

Have you tried this:
webBrowser1.Document.GetElementById("MySite.condition_s").selectedIndex = 1

Try this.
HtmlDocument document = webBrowser1.Document;
HtmlElement siteCondition = document.GetElementById("MySite.condition_s");
var option = siteCondition.Children.Cast<HtmlElement>().First(x => x.GetAttribute("value").Equals("First"));
option.SetAttribute("selected", "selected");

here is your solution just go through example: http://www.vbforums.com/showthread.php?701093-Webbrowser-Control-Select-Dropdownlists-option
or
http://social.msdn.microsoft.com/Forums/en-US/Vsexpressvb/thread/b1273d78-d4af-49e0-9238-6f86e9952484/

I founded that if you just invoke click one by one, you should be able to find what you want by doing a for loop click inside it.
HtmlElement site = this.webBrowser2.Document.GetElementById("myId");
foreach (HtmlElement item in site.Children)
{
if (item.InnerText.ToString() == "something")
{
item.InvokeMember("Click");
break;
}
else
{
item.InvokeMember("Click");
}
}

100% working code (tested on win7 - ie11)
taken from:
c# | WebBrowser control - programmatically select item on html select
http://mdb-blog.blogspot.com/2016/12/c-browser-control-programmatically.html
HtmlElementCollection col = webBrowser1.Document.GetElementsByTagName("select")
foreach (HtmlElement heItem in col)
{
if (heItem.GetAttribute("className").Contains("exampleClassName") == true)
{
heItem.SetAttribute("selectedIndex", "3"); // select value at #3
break; // incase of needed...
}
}

Related

Select an ID if it's a number?

Is there a way to select a list item from an aspx file from a .cs file to make the <li> visible. The ID for the <li> are numbers.
The reason why they are numbers is because this page is a custom view editor for the website, it is updating a database and then loads the correct view for the user. I need to hide some items for certain users on this page.
Snippet from aspx page:
<div id="connectedSortableLists">
<ul id="unselected" class="connectedSortable">
<li class="ui-state-highlight" id="0">Log #</li>
<li class="ui-state-highlight" id="19">Log date</li>
</ul>
</div
I've tried adding in runat="server" to various places however had no luck.
Is there a way to select like for a grid-view like : grdv_dummy.Columns[29].Visible = false; ?
I want to select the li by an ID to set the visibility to false to do it server side based on user. When the new custom view is saved, database will be updated with the id number. When I try with id="item" the desired page tries to load I get the error Input string was not in a correct format; due to the database having an entry of 'item'.
I feel as though i'm overlooking something although more likely completely wrong.
Thank you for your time
You will definitely need runat=server on your li elements (or ul element). Then you need to add letters to your ids - you can't have just numbers as an id. So something like "item". Then in you .cs file use something like:
private HtmlElement FindListItem(int id)
{
HtmlElement listItem = this.FindControl("item" + id.ToString()) as HtmlElement;
if (listItem != null && listItem.TagName == "li")
{
return listItem;
}
return null;
}
Basically FindControl() is what you need. Then you can use it like:
var item = FindListItem(19);
if (item != null)
{
item.Visible = false;
}
Oh an depending on how you've setup your code, you'll use it either in Page_Load or onPreRender...
you cannot directly access it in server side.However, you can call javascript function from server side which can enable\disable it.
At server side
string jsFunc = "DisableHtmlLi(" + iterator + ")";
ScriptManager.RegisterStartupScript(this.Page, Page.GetType(), "DisableHtmlLi", jsFunc, true);
At Client side
<script type="text/javascript" language="javascript">
function DisableHtmlLi(index) {
var element = document.getElementById(index);
element.visible= false;
}
</script>
Managed to find a way round the problem. I know that li shouldn't be put in other li , but it worked for me.
ASPX Altered
<div id="connectedSortableLists">
<ul id="unselected" class="connectedSortable">
<li class="ui-state-highlight" id="0">Log # </li>
<li class="ui-state-highlight" id="19">Log date</li>
<li runat="server" id="full" visible="false">
<li class="ui-state-highlight" id="32">Days Country</li>
<li class="ui-state-highlight" id="33">Days total</li>
</li>
</ul>
</div
.CS Page
full.Visible = true;

Parsing Radio button name only bringing up one value

I have written some code to parse the name from some radio buttons.
<div id="First" class="Size-Inputs">
<input rel="8" type="radio" value="13051374" name="idProduct-13051359"/> <span rel="L">L</span>
<input rel="8" type="radio" value="13051373" name="idProduct-13051359"/> <span rel="M">M</span>
<input rel="8" type="radio" value="13051372" name="idProduct-13051359"/> <span rel="S">S</span>
<input rel="8" type="radio" value="13051375"name="idProduct-13051359"/> <span rel="XL">XL</span> </div>
The problem which I am having when I try to parse the span rel to get the size names eg L,M,S,XL it is only coming up with the value L four times.
The code I am using is;
HtmlNodeCollection link = doc.DocumentNode.SelectNodes("//*[#id='First']/input");
if (link != null)
{
foreach (HtmlNode item in link)
{
string name = item.SelectSingleNode("//*[#id='First']/span").InnerText;
Console.WriteLine(name);
}
Console.ReadLine();
}
I was just wondering why the it is only picking up one value and printing it four times and how can you make it pick up the span rel for each of the variant input. Thanks for any help which you can provide
It seems that you don't need <input> element but <span> element. And <span> is not child of <input>. So assuming that it isn't typo or paste error, you can select <span> directly without selecting <input> element first :
HtmlNodeCollection link = doc.DocumentNode.SelectNodes("//*[#id='First']/span");
if (link != null)
{
foreach (HtmlNode item in link)
{
string name = item.InnerText;
Console.WriteLine(name);
}
Console.ReadLine();
}

HtmlAgilityPack issue with HTML

I want to get title, image src and other details but here is an issue
<div class="thumb-container">
<a class="featured" title="Spectacularly " href="http://www.site.com"></a>
<div rel="0" id="property_image_1181140" class="thumb">
<a title="*Want this title*" href="*http://www.wanttogetthislink.com*">
<img style="width: 190px; height: 127px; left: -11px; top: 0px;" alt="Spectacularly upgraded 5 bed Family Villa For Sale" src="http://c1369013.r13.cf3.rackcdn.com/1181140-1-mini.jpg">
</a>
</div>
<div class="description-listing">
<div class="heading">
<div class="type">
<label>*5,900* sq.ft.,</label>
<span>*Villa*</span>
<p class="bedroom"><em>*5*</em></p>
<p class="bathroom"><em>*6*</em></p>
</div>
<p class="amount">
<label>AED</label>
<strong>*5,120,000*</strong>
</p>
</div>
Here is my code
var allCarResults = rootNode.SelectNodes("//div[normalize-space(#class)='general-listing']");
foreach (var carResult in allCarResults)
{
var dataNode = carResult.SelectSingleNode(".//div[#class='thumb']");
var carNameNode = dataNode.SelectSingleNode(".//a");
}
Here i want to get everything in **
i do not know how to do that..
The principle is pretty much the same, you'll need to write an XPath for each item and select it from a common anchor:
HtmlNode thumbContainer = doc.DocumentNode.SelectSingleNode("//div[#class='thumb-container']");
HtmlNode link = thumbContainer.SelectSingleNode("./div[#class='thumb']/a");
string linkTitle = link.Attributes["title"].Value;
string linkHref = link.Attributes["href"].Value;
HtmlNode label = thumbContainer.SelectSingleNode("./div[#class='description-listing']/div[#class='heading']/div[#class='type']/label");
string labelText = label.InnerText;
// ... Similar for other items
Alternatively you could iterate through each HtmlNode and its children, then for each item match it against a list of items you're after.

Recursively create accordion html from list of links in C#

I am scraping a remote page for links, which I have in a List. I am trying to get the list printed out as necessary for a jquery accordion. I have the html no problem, but my loops are off a bit and aren't nesting properly.
Here is an example of the List:
Heading 1
link1
link2
link3
Heading 2
link4
link5
link6
So here is how I need to get the html formatted:
<div data-role="collapsible" data-collapsed="true">
<h3>Heading 1</h3>
<p>
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
</ul>
</p>
</div>
<div data-role="collapsible" data-collapsed="true">
<h3>Heading 2</h3>
<p>
<ul>
<li>link4</li>
<li>link5</li>
<li>link6</li>
</ul>
</p>
</div>
And here is the code I have so far, it should be mentioned I am using the HTMLAgilityPack:
HtmlNodeCollection OneHome = document.DocumentNode.SelectNodes("//div[#id='accordion1']");
var OneHomelinks = OneHome.Descendants("a")
.Select(a => a.OuterHtml)
.ToList();
foreach (string link in OneHomelinks)
{
if (link.Contains('#'))
{
Response.Write("<div data-role=\"collapsible\" data-collapsed=\"true\">");
Response.Write("<h3>" + link + "</h3>");
Response.Write("<p>");
Response.Write("<ul>");
}
if (!link.Contains('#'))
{
Response.Write("<li>" + link + "</li>");
} else {
Response.Write("</ul>");
Response.Write("</p>");
Response.Write("</div>");
}
}
Basically I am trying to pull out the Headings by using the '#' in the href, and resetting the at that point - but something is off, the lists aren't being properly formed. Any help is super appreciated here!
CURRENT OUTPUT
<div data-role="collapsible" data-collapsed="true">
<h3>Heading 1</h3>
<p></p>
<ul></ul>
<p></p>
</div>
<li><a href="link1.html>link1</a></li>
<li><a href="link2.html>link2</a></li>
<li><a href="link3.html>link3</a></li>
<div data-role="collapsible" data-collapsed="true">
<h3>Heading 2</h3>
<p></p>
<ul></ul>
<p></p>
</div>
<li><a href="link4.html>link4</a></li>
<li><a href="link5.html>link5</a></li>
<li><a href="link6.html>link6</a></li>
Edit: Logic in the wrong spot, whoops!
Edit 2: Once more with logic placement.
I think this should work for you:
HtmlNodeCollection OneHome = document.DocumentNode.SelectNodes("//div[#id='accordion1']");
var OneHomelinks = OneHome.Descendants("a")
.Select(a => a.OuterHtml)
.ToList();
var headerCount = 0;
foreach (string link in OneHomelinks)
{
var prevCounter = headerCount;
if (link.Contains('#'))
{
headerCount++;
if (headerCount != 1 && headerCount > prevCounter) {
Response.Write("</ul>");
Response.Write("</p>");
Response.Write("</div>");
}
Response.Write("<div data-role=\"collapsible\" data-collapsed=\"true\">");
Response.Write("<h3>" + link + "</h3>");
Response.Write("<p>");
Response.Write("<ul>");
}
else {
Response.Write("<li>" + link + "</li>");
}
}
Response.Write("</ul>");
Response.Write("</p>");
Response.Write("</div>");

Can I make one row show at a time in a table?

I have a javascript function that toggles the display for rows in a table. The dilemma is that I would like to display one row at a time. What is a neat way to do this?
function optionSelected() {
var optionSelect = document.getElementById('ddlSelect');
var strTest = optionSelect.options[optionSelect.selectedIndex].value;
var rowHeader = document.getElementById(strTest);
var row = document.getElementById(strTest);
if (rowHeader.style.display == '') {
rowHeader.style.display = 'none';
row.style.display = 'none';
}
else {
rowHeader.style.display = '';
row.style.display = '';
}
}
<select id="ddlSelect" onchange="optionSelected()">
<option value="optionA">A</option>
<option value="optionB">B</option>
<option value="optionC">C</option>
<option value="optionD">D</option>
</select>
<table id="tableList">
<tr id="optionA"><td>DisplayA</td></tr>
<tr id="optionB"><td>DisplayB</td></tr>
<tr id="optionC"><td>DisplayC</td></tr>
<tr id="optionD"><td>DisplayD</td></tr>
</table>
simple with jquery
$('tr').hide();
$('#'+strTest).show();
This is your vanilla Javascript solution (although I'd rather go with jQuery):
function optionSelected() {
var sel = document.getElementById('ddlSelect');
for (var i=0; i<sel.options.length; i++) {
document.getElementById(sel.options[i].value)
.style.display = sel.options[i].selected ? '' : 'none';
}
}​
Also, if you want to initialize your display, you should call optionSelected() once in an onLoad handler.
Instead of looping on DOM nodes, you can change style rules and use the speed of the CSS selectors instead.
Here is an example to show one line at a time and stay.If you want to remove them at each selection you can clear the style each time you make a selection.
<body>
<style id="styles">
table tr{
display:none;
}
</style>
<select id="ddlSelect" onchange="optionSelected()">
<option value="optionA">A</option>
<option value="optionB">B</option>
<option value="optionC">C</option>
<option value="optionD">D</option>
</select>
<table>
<tr id="optionA"><td>DisplayA</td></tr>
<tr id="optionB"><td>DisplayB</td></tr>
<tr id="optionC"><td>DisplayC</td></tr>
<tr id="optionD"><td>DisplayD</td></tr>
</table>
<script>
function optionSelected() {
var optionSelect = document.getElementById('ddlSelect'),
styles = document.getElementById('styles'),
selector = '#' + optionSelect.options[optionSelect.selectedIndex].value,
rule = 'display:block';
if(styles.styleSheet){
styles.styleSheet.cssText = selector + '{' + rule + '}';
}else{
styles.appendChild(document.createTextNode(selector + '{' + rule + '}'));
}
}
</script>
</body>

Categories