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
Related
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.
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`m having a webBrowser control with some span elements.
Now user clicks on one of them, I do some manipulations and after that I need to select clicked element in browser. How can I do this?
HtmlElement hitElement = exerciseTextEditorControl.Document.GetElementFromPoint(e.ClientMousePosition);
if (lastHitElement == null)
return;
// Some stuff elided
// Now need to make a selection of this element in web browser
I know I can use IHTMLTxtRange for selecting some text, but how can I do similar thing with HtmllElement?
Thanks in advance.
Found an answer. In case someone needs this as well:
public void SetSelectedElement(HtmlElement element)
{
IHTMLSelectionObject selection = HtmlDocument2.selection;
var htmlTxtRange = selection.createRange() as IHTMLTxtRange;
var iHtml = element.DomElement as IHTMLElement;
htmlTxtRange.moveToElementText(iHtml);
htmlTxtRange.select();
}
I've read a few articles regarding getting values back from a modal popup in an ASP .NET page, but they all seem to use JavaScript to accomplish this which isn't really want I want to do if possible.
I have a web user control which has a repeater that I populate from a list into a table. Each row has a link button which has a redirect url with a value as a query string.
Then I have another web user control which is just a link button with a panel and the repeater web user control that once clicked shows the actual modal popup.
Is it possible to get a value from the web user control once the link button on the repeater is clicked without having to redirect to the same page? I basically want to click on the link, show the modal and once closed, want to access the value.
I'm populating the repeater with the links as follows:
string linkUrl = "";
string action = "";
if (Request.QueryString["action"] != null)
{
action = Request.QueryString["action"];
switch (action)
{
case "SetupCompany":
{
linkUrl = "<a href=CreateCompanies.aspx?companyId=";
break;
}
case "ViewCompany":
{
linkUrl = "<a href=ViewCompany.aspx?companyId=";
break;
}
}
}
CompaniesBusinessManager mgr = new CompaniesBusinessManager();
var companies = mgr.GetCompanies(txtCompanyName.Text, txtRegistrationNumber.Text);
if (linkUrl != "")
{
foreach (var c in companies)
{
c.Name = linkUrl + c.Id.ToString() + "&action=" + action + ">" + c.Name + "</a>";
}
}
rptrCompanies.DataSource = companies;
rptrCompanies.DataBind();
if you don't want the page to be redirected, you will need to use javascript.
There is now way you can pass values from different controls without going back to the server.
In case you keep it without the javascript:
I think you need to pass values from one user control to another. I used to accomplish this by firing reachable events between them.
For example:
in your parent view:
<uc:YourUserControl runat="server" ID="UserControl_Test"
OnYourCustomAction="UserControl_YourUserControl_YourCustomAction" />
In your user control:
public event EventHandler<CustomActionEventArgs> YourCustomAction;
also in the same user control create a public trigger method to be access from others usercontrols
public void TriggerCustomActoinEvent(CustomActionEventArgs EventArgs)
{
if (this.YourCustomAction!= null)
{
this.YourCustomAction(this, EventArgs);
}
}
Hope this help, in on my way to home this was from my mind!
Without a page postback or JavaScript it not really possible. If you are using modal popups you are already using JS, so why not just get the value in JS? You could setup an event handler for all repeater buttons and if they are loaded via ajax use something like this to attach the event handler:
$(document).on('click', '.repeaterButton', function(e) {
var valueOfBtnClicked = $(this).val();
// Do something else
});
I have been trying for a few days now and still have had no success in programmatically clicking on this div. All of the other input fields and buttons are working fine using InvokeMember("click") and RaiseEvent("onclick"), but I am unable to click on the following div:
<div class="pump request"> onclick="$(this).push('kjhzsd94vibjktj584ed01', null, event)" </div>
This div is repeated several times on a page, but I just want to click on the first occurrence.
This is what I have done so far:
HtmlElementCollection c1 = wbc1.document.GetElementsByTagName("div");
foreach (HtmlElement e2 in c1)
{
if (e2.GetAttribute("class").Contains("pump request"))//also this condition is not returning true
{
e2.RaiseEvent("onclick");
}
}
#bleepzter
what if "somecontrol" is a class of the div instead of div's id?
since in my case i have div class "pump request" so (if i write "pump request" as somecontrol in above example) it return me Null in someDiv
<div class="pump request"> onclick="$(this).push('kjhzsd94vibjktj584ed01', null, event)" </div>
#Cameron
yep i did entered the break; but the problem is the if condition never returns true so
HtmlElementCollection c1 = wbc1.document.GetElementsByTagName("div");
foreach (HtmlElement e2 in c1)
{
if (e2.GetAttribute("class").Contains("pump request"))//--> This condition is not returning true
{
e2.RaiseEvent("onclick");
break;
}
}
#Ilya Kogan
yea i just did a watch on e2.GetAttribute("class") and the weird thing happened that being reading the actual div (which i want to click) the value of class was empty :-o
try this one
if (e2.GetAttribute("className").Contains("pump request"))
{
e2.InvokeMember("Click");
}
you can try this piece of code by using a web browser control.
// browser is the web browser control
HtmlElementCollection col = browser.Document.GetElementsByTagName("div");
foreach (HtmlElement helemnt in col)
{
if (helemnt.InnerText !=null && helemnt.InnerText=="something")
{
helemnt.InvokeMember("Click");
break; // break the loop
}
}
It is simple. Here is an example which assumes your browser control is called browser, and the div you are looking for is called somecontrol (i.e. the id of the div is somecontrol):
HtmlElement someDiv = browser.Document.All["somecontrol"];
object someDivElement = someDiv.DomElement;
MethodInfo clickMethod = someDivElement.GetType().GetMethod("click");
clickMethod.Invoke(someDivElement, null);
All this is possible via reflection.