I cant seem to figure out how to put the value text into a texbox.Text on Webbrowser C# because with this website the value changes and there are duplicates of the input code and cant pinpoint Webbrowser to put the changing value username in a textbox.Text as seen in screenshot below.
I hope someone knows how to do this with the Webbrowser in C#
Thanks in advance.
Problem Screenshot
This is the website I am trying to get the username from: fakepersongenerator
You'd need to manually scan through the DOM and find the element based on it's xpath. Like this:
webBrowser.DocumentCompleted += (o, e) =>
{
var frame1 = webBrowser.Document.Body.GetElementsByClassName("frame-1");
if (frame1.Count > 0)
{
var rows = frame1[0].GetElementsByClassName("row no-margin");
if (rows.Count > 4)
{
var usernameForm = rows[4].GetElementsByClassName("form-control");
if (rows.Count > 0)
{
// Do something with value here
Console.WriteLine(usernameForm[0].GetAttribute("value"));
}
}
}
};
webBrowser.Navigate("http://www.fakepersongenerator.com/Index/generate");
Extension class to :
internal static class Utils
{
internal static List<HtmlElement> GetElementsByClassName(this HtmlElement doc, string className = "")
{
var list = new List<HtmlElement>();
foreach (HtmlElement e in doc.All)
if (e.GetAttribute("className") == className)
list.Add(e);
return list;
}
}
There isn't really a way in the default web browser to detect changes after a page load, so if you wanted to monitor for changes, you'd have to set up a BackgroundWorker or Timer to poll the browser and manually look for a value change.
Related
I need to monitor changes in the google chrome url textbox. I have the code the finds the url and correctly reads it.
AutomationElement elementx = element.FindFirst(System.Windows.Automation.TreeScope.Descendants, conditions);
return ((ValuePattern)elementx.GetCurrentPattern(ValuePattern.Pattern)).Current.Value as string;
elementx is the url textbar and the url is returned
Now
I need to monitor the url textbar for text changes. I found some code on stackoverflow but it doesnt work . Handling ProgressBar's Value change with UIAutomation
I have used an app called accevent.exe and see that it is indeed possible to monitor for text changes as is evident per the screenshot.
So basically I need a way to monitor and report changes to the url text.
and here are some settings
ValuePattern chromeValuePattern;
AutomationPropertyChangedEventHandler propChangeHandler = null;
chromeValuePattern = elementx.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
propChangeHandler += new AutomationPropertyChangedEventHandler(OnPropertyChange);
Automation.AddAutomationPropertyChangedEventHandler(elementx,
System.Windows.Automation.TreeScope.Subtree, propChangeHandler,
AutomationProperty.LookupById(UIA_PropertyIds.UIA_ValueValuePropertyId));
private void OnPropertyChange(object src, AutomationPropertyChangedEventArgs e)
{
AutomationElement sourceElement = src as AutomationElement;
if (e.Property == AutomationProperty.LookupById(UIA_PropertyIds.UIA_ValueValuePropertyId))
{
Debug.WriteLine(e.NewValue);
}
else
{
}
}
I just try to understand the concept of in web browser control c# win app.
I have created a Windows app with web browser control. I have called a web page (which is my own) and try to set value in the web page from my app.
When i try with Google
webBrowser1.Navigate("http://google.com/search?q=" + "C#");
it works fine.
When i try in this way, it is not working.
HtmlElement textArea = webBrowser1.Document.All["q"];
textArea.InnerText = "dsfs";
Can anyone help me to achieve this?
You will need to wait for the WebBrowser to load before you access it (otherwise Document will be null until loaded) - subscribe a DocumentCompleted event handler for this. Also Document.All["q"] will return the first element with the name "q".
webBrowser1.Navigate("http://stackoverflow.com/questions/30431004");
webBrowser1.DocumentCompleted += (o, args) =>
{
var ele = webBrowser1.Document.All["q"];
if (ele.TagName.ToLower() == "input")
{
ele.InnerText = "dsfs";
}
};
If you want to change more than one such element, or if you want to locate elements by Id, Tag name etc, you will need to iterate the collection:
foreach (HtmlElement ele in webBrowser1.Document.All)
{
if (ele.TagName.ToLower() == "input")
{
ele.InnerText = "dsfs";
}
}
I am working on a windows application where I embedded webbroswercontrol. I am trying to post sample message to a open facebook group. I am unable to change value of a textbox with c#. When ever I automate click it says textbox value is null. What would be the fix?
<input type="hidden" autocomplete="off" class="mentionsHidden"
name="xhpc_message" value="lklklkl">
HtmlElement textBox = this.FindControlByName("xhpc_message",
this.webBrowser.Document.All);
//Click Code
var elements = webBrowser.Document.GetElementsByTagName("button");
foreach (HtmlElement element in elements)
{
// If there's more than one button, you can check the
//element.InnerHTML to see if it's the one you want
if (element.InnerText.Contains("Post"))
{
if (textBox.InnerText.Trim() == "Write something...")
{
textBox.Focus();
textBox.GetAttribute("value").Equals("Test Message");
IHTMLElement nativeElement = element.DomElement as IHTMLElement;
nativeElement.click();
break;
}
}
}
1) I suggest you to ensure, that textbox is null, not the textBox.InnerText. Usually inner text for elements is null, so its better to check the "placeholder" attribute and update the code with:
// if (textBox.InnerText.Trim() == "Write something...")
if (textBox.GetAttribute("placeholder") == "Write something...")
2) This code doesn't set the value. It gets the value and compares to "Test message".
textBox.GetAttribute("value").Equals("Test Message");
Just use SetValue instead.
textBox.SetAttribute("value", "Test message");
3) Ensure, that all operations are made after page is loaded.
public SomeFormName()
{
...
webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
}
void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs args)
{
// put your code here
}
4) Not sure, how the FindControlByName is working, so check a simple LINQ query to ensure that textbox is found.
var textbox = webBrowser.Document.All.OfType<HtmlElement>()
.Where(item => item.Name == "xhpc_message")
.FirstOrDefault()
;
Use the code below after the Document complete event has been fired completely in a separate function, after commenting your code.The URL in the webbrowser should be holding the Group Page on which the post is to happen.
private void AfteDocumentLoads()
{
HtmlElementCollection textBox = webBrowser.Document.GetElementsByTagName("textarea").GetElementsByName("xhpc_message");
HtmlElementCollection button = webBrowser.Document.GetElementsByTagName("button");
foreach (HtmlElement element in textBox)
{
foreach (HtmlElement btnelement in button)
{
if (btnelement.InnerText == "Post")
{
element.Focus();
element.InnerText = txtPortalUserId.Text.ToString();
btnelement.InvokeMember("Click");
}
}
}
}
I was also stuck as it was not posting earlier because I was using WebBrowser class to get current WebBrowser. Result was that the text was inputted to the Group as a 'dim' Comment. Even if I clicked manually on FB page it would say "This status update appears to be blank. Please write something or attach a link or photo to update your status."
I used the page's webbrowser & it worked cos' it came in proper manner on the page. Also little bit of changes are there in the LOCs
I got an userControl that contains a searchBox.
This UserControl is inside another one.
I got a strange behavior while i'm searching, because the suggestionCollection works in a strange way.
Example :
in the searchBox i write something all works perfectly, if i choose the item it also works.
But if i try to use backspace (after the choose) i got no suggestion.
I cannot understand why it doesn't work.
That's the code
//var deferral = args.Request.GetDeferral(); //it seems to not influence the behavior
var suggestionCollection = args.Request.SearchSuggestionCollection;
try
{
TransporterExt tr_search = new TransporterExt();
//queryText is a string inserted in the searchBox
if (string.IsNullOrEmpty(queryText)) return;
tr_search.name = queryText;
suggested.Clear(); //that's a collection..
//just a search that return a collection of objects TransporterExt
querySuggestions = await TransporterService.Search_StartsWith(tr_search);
if (querySuggestions.Count > 0)
{
int i = 0;
foreach (TransporterExt tr in querySuggestions)
{
string name = tr.name;
string detail = tr.trId.ToString();
string tag = i.ToString();
string imageAlternate = "imgDesc";
suggestionCollection.AppendResultSuggestion(name, detail, tag, imgRef, imageAlternate);
this.suggested.Add(tr);
i++;
}
}
}
catch (System.ArgumentException exc)
{
//Ignore any exceptions that occur trying to find search suggestions.
Debug.WriteLine(exc.Message);
Debug.WriteLine(exc.StackTrace);
}
//deferralComplete(); //it seems to not influence the behavior
The problem is that: all the variables have the right value, but the suggestion panel appears only if i make a particular search: it appears when i change the first letter of search, or after an wrong seach
What appends when i make a search
What appends if i use the backspace, and i what i want to fix
As i said, all works perfectly, after the "backspace" action the suggestionCollection got the right value...but the panel is missing.
Could someone help me?
You can use SearchBox and SuggestionRequested event to fire the event when type on the SearchBox. I will show an Example
<SearchBox x:Name="SearchBoxSuggestions" SuggestionsRequested="SearchBoxEventsSuggestionsRequested"/>
and write the SearchBoxEventsSuggestionsRequested handler in the code behind
private void SearchBoxEventsSuggestionsRequested(object sender, SearchBoxSuggestionsRequestedEventArgs e)
{
string queryText = e.QueryText;
if (!string.IsNullOrEmpty(queryText))
{
Windows.ApplicationModel.Search.SearchSuggestionCollection suggestionCollection = e.Request.SearchSuggestionCollection;
foreach (string suggestion in SuggestionList)
{
if (suggestion.StartsWith(queryText, StringComparison.CurrentCultureIgnoreCase))
{
suggestionCollection.AppendQuerySuggestion(suggestion);
}
}
}
}
You can add the keyword to SuggestioList, and it will show in the dropdown when you type on the Searchbox.
Create the SuggestionList
public List<string> SuggestionList { get; set; }
initialize the list
SuggestionList = new List<string>();
and add keywords to the list
SuggestionList.Add("suggestion1");
SuggestionList.Add("suggestion2");
SuggestionList.Add("suggestion3");
SuggestionList.Add("suggestion4");
SuggestionList.Add("Fruits");
Thanks.
I need some help because I keep getting a StaleElementReference when I try to parse a list of a tags to click.
What I have done is on page land I iterate through the page and generate an object List<> with with all the a tags
private List<IWebElement> _pageLinks;
public List<IWebElement> pageLinks
{
get
{
if (_pageLinks == null)
{
_pageLinks = InfoDriver.FindElements(By.TagName("a")).ToList();
}
return _pageLinks;
}
}
Then I want to parse this list, and click each one and then go back to the page it was referenced from.
private static SeleniumInformation si = new SeleniumInformation(ffDriver);
si.pageLinks.ForEach(i =>
{
i.Click();
System.Threading.Thread.Sleep(1000);
ffDriver.Navigate().Back();
});
What happens is that after the first click it goes to the new page and then goes back to the starting page but it can't get the next link. I've tried setting it to a static element, setting a backing field so that it checks to see if there is data there already however it appears that on click the IwebElement looses the list and it doesn't rebuild the list either so I get a StaleElementReference exception not handled and element not found in cache.
Is this a bug in Selenium with the IWebElement class or am I doing something wrong? Any help would be greatly appreciated.
This is the expected behavior. You left the page the element was on. When you navigated back, it is a new page and that element is no longer on it.
To work around this I would suggest passing around Bys instead, if you can. Assuming your anchorlinks all have unique hrefs, you could instead generate a list as follows (java code, but should translate to c#):
private static List<By> getLinks(WebDriver driver)
{
List<By> anchorLinkBys = new ArrayList<By>();
List<WebElement> elements = driver.findElements(By.tagName("a"));
for(WebElement e : elements)
{
anchorLinkBys.add(By.cssSelector("a[href=\"" + e.getAttribute("href") + "\"]"));
//could also use another attribute such as id.
}
return anchorLinkBys;
}
I don't know the makeup of your page so I don't know if it is possible to generate By's dynamically that uniquely identify the elements you want. For example if all the elements have the same parent, you could use the css level 3 selector nth-child(n). Hopefully you get some ideas from the above code.
private void YourTest()
{
IWebDriver browserDriver = new FirefoxDriver();
browserDriver.Navigate().GoToUrl(pageUrl);
int linkCount= browserDriver.FindElements(By.TagName("a")).Count;
for (int i = 0; i <= linkCount-1; i++ )
{
List<IWebElement> linksToClick = browserDriver.FindElements(By.TagName("a")).ToList();
linksToClick[i].Click();
System.Threading.Thread.Sleep(4000);
if(some boolean check)
{
//Do something here for validation
}
browserDriver.Navigate().Back();
}
broswerDriver.Quit();
}