Endless loop with InvokeMember c# - c#

I'm trying to mark some checkboxes and then submit a form using webbrowser, I succeeded, the problem is that my program is getting endless, It appears the form submitted, and then my form before being submitted, again submitted and again before being submitted and again...again....again.... infinitely so. I do not understand why.
I have realized that it happens in this part:
form.InvokeMember ("submit");
This is my code
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate("https://www.mysite.com");
}
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
this.Text = e.Url.ToString() + " loaded";
webBrowser1.Document.GetElementById("check1").InvokeMember("CLICK");
webBrowser1.Document.GetElementById("check2").InvokeMember("CLICK");
webBrowser1.Document.GetElementById("check3").InvokeMember("CLICK");
webBrowser1.Document.GetElementById("check4").InvokeMember("CLICK");
webBrowser1.Document.GetElementById("check5").InvokeMember("CLICK");
foreach (HtmlElement form in webBrowser1.Document.Forms)
{
if (form.Name == "SearchForm")
{
form.InvokeMember("submit");
}
}
}
private void webBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
{
this.Text = "Navigating";
}

Well you've said that any time you finish loading a page, you want to submit the search form. So when that submit finishes, it will finish loading the page... and you'll trigger the same event. It's an entirely natural loop.
You should ask yourself what condition you want to detect that means you should submit the form when the page has finished loading. Should it only be when there isn't already something in the search box, for example? Or make it change based on the URL? Or perhaps you simply want to unhook the event handler for "document completed" before you submit the form? We can't really tell without more context, but that's why you're setting that behaviour.

Victor, try having a different form (*.aspx) for the submit action.

Related

C# PerformClick method in invisible form

I am stuck on using a PerformClick method. I have a main form which is called mymainform, and I have some subforms. When loading main form, I am creating subforms and hide them with Form Visibility and access some elements on subforms.
My problem is clicking a button on subform1 from MainForm. I have written the below code and it didn't work. Normally DayModeButton changes the boolen; isDay = !isDay
After clicking the button1 on mainform it doesn't change the isDay boolen.
private void button1_Click(object sender, EventArgs e)
{
mysubform1.DayModeButton.PerformClick();
button1.Text = mysubform1.isDay.ToString();
}
If I write this code it works, but I don't want to show and hide the form because it is not a good view for users.
private void button1_Click(object sender, EventArgs e)
{
mysubform1.Visible=true;
mysubform1.DayModeButton.PerformClick();
button1.Text = mysubform1.isDay.ToString();
mysubform1.Visible=false;
}
Can anyone help me in performing a Click event in invisible forms?
Thanks
Make sure your DayModeButton is Public and not Private.

Why can I not call a form object in two events?

I'm making like a add contact form with two buttons, ADD CONTACT and EDIT CONTACT. When a user clicks add contact, it pops up another form where the user can add contact information.
I want to give them the option to edit that info by clicking the EDIT CONTACT button which should pop up the SAME form.
However its not letting me call the object of the form twice, saying that I cannot press the edit button after the add button.
How do I call a form object twice?
//instatiating an object of the form
FormContact contactForm = new FormContact();
public FormManager()
{
InitializeComponent();
}
private void btnAdd_Click(object sender, EventArgs e)
{
//displaying it when the user clicks add button
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
//trying to display it again but gives this exception
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
contactForm.Show();
}
Error:
///System.ObjectDisposedException: 'Cannot access a disposed
///object.
///Object name: 'FormContact'.'
The problem is you're closing the form after you've shown it.
You click the Show button
Your only instance of the form is shown
You close it with the X in the top corner
The runtime destroys the form (disposes it) after it is closed
You try to show it again but this this it's gone, trashed, doesn't exist any more, waiting to be garbage collected
Either make a new form each time you open it (to reduce code clutter, assign this same event handler to both button clicks, or copy paste it out twice if you want them to be coded differently eventually):
private void btnAddOrEdit_Click(object sender, EventArgs e)
{
new FormContact().Show();
}
Or intercept the FormClosing event of the FormContact form and cancel the closing, and perform a Hide() instead so that instead of being destroyed your form is made invisible. It will then still exist and can be Show()n the next time. To handle the event, open the FormContact designer, click anywhere in the form background, click lightning bolt in properties grid, double click the FormClosing entry:
private void FormClosing(object sender, FormClosingEventArgs e){
e.Cancel = true;
this.Hide();
}
Which method you choose depends how you want your program to behave:
If you make a new form each time, and you Show instead of ShowDialog your user could click Add twice and see two forms. Then could click Add 10 times and see 10 forms. Using ShowDialog means that the main window won't accept any more clicks until the FormContact is closed. You might or might not want this either
If you Hide (not close; hiding is different from closing) and Show the same form rather than making a new one then the user can click Add 10 times but they still only see one form
FormContact contactForm = new FormContact(); is a Member variable, it's scope is Private and is visible to the entire class.
After you first Show the form:
contactForm.Show();
The form is already showing. Therefore if you call Show again, it won't do anything as the instance of the form/class is already showing.
If you want to show two instances of the form, you will need to instantiate two instances eg:
private void btnAdd_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
FormContact contactForm = new FormContact();
contactForm.Show();
}
Or make two instances of it:
FormContact contactForm1 = new FormContact();
FormContact contactForm2 = new FormContact();
private void btnAdd_Click(object sender, EventArgs e)
{
contactForm1.Show();
}
private void btnEdit_Click(object sender, EventArgs e)
{
contactForm2.Show();
}
Or add a argument in the parameter of the Constructor to indicate Add or Edit, eg:
public class FormContact
{
public FormContact(int id)
{
if (id > 0)
{
//Load contact for Editing
}
else
{
//Clear all fields for Adding
foreach(var ctrl in this.Controls)
{
if (ctrl Is TextBoxBase) ctrl.Text = string.Empty
//TODO other controls types... if (ctrl Is ....
}
}
}
}
Then you can call it passing a contactID to edit or 0 to add:
FormContact contactForm = new FormContact(contactID);
contactForm.Show();
I've got another answer, in both methods simply show your form modally:
contactForm.ShowModal();

C# reach click button in webbrowser?

I want to click event button in webbrowser object.
Button is clicked I want to reach out and write the code? For example, the login button is clicked on the webbrowser object in the pop-up on the site to capture the event and would like to write the code?
I write an example for you(how get event clicked button):
private void Form1_Load(object sender, EventArgs e)
{
//Or navigate to your url
webBrowser1.DocumentText = "<html><body><button id=\"btn1\" type=\"button\">Click Me!</button><button id=\"btn2\" type=\"button\">Click Me!</button></body></html>";
}
Call Click event:(when page loaded)
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
webBrowser1.Document.Click += new HtmlElementEventHandler(Document_Click);
}
Get Active Element When User click on document
void Document_Click(object sender, HtmlElementEventArgs e)
{
//Check Element is Button
if (webBrowser1.Document.ActiveElement.TagName == "BUTTON")
{
if (webBrowser1.Document.ActiveElement.Id== "your button id")
{
//Do someting
}
}
}
If I understand correctly, you're using the WebBrowser control in C# WinForms and you would like to fire an event when a button is clicked.
The control doesn't have a click event, but the Document does. To do this you can use WebBrowser.Document.Click event and then loop through the HTML elements to find the one that was clicked.
web.Document.Click += new HtmlElementEventHandler(Document_Click);
This link will help also: webbrowser-control-get-element-by-type

WebBrowser control - wait for page loading after submit form

I am new to c# and its concepts, so i am sorry if this question is kind of dumb.
I try to do some automatation using the winforms webbrowser control
elements = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement element in elements)
{
if (element.GetAttribute("value") == "Anzeigen")
element.InvokeMember("click");
}
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete) Application.DoEvents();
// do some math on recived html
// ......
// show results
MessageBox.Show(numPlanets.ToString() );
So, to explain it:
Im looking for a Button with the value "Anzeigen", simulate a click on it, then wait till NEW page is loaded and do my calculations then.
Unfortunately my calculations are done on the OLD HTML content, because its not waiting for the page to load. Strangely if i enter an Thread.Sleep(5000); after the foreach loop, this Sleep is executed BEFORE the click is simulated, and the calculation fails also.
I just need some synchronous behavior for that click, withouth using an event.
Hope u can help me with that, sorry for my bad english
EDIT:
Solved it like this:
Variable bool webbbrowserfinished = false inside the class, if i want synchronous behavior, i do it like this:
webbrowserfinished = false;
// do navigation here
while (!webbrowserfinished)
{
Application.DoEvents();
Thread.Sleep(100);
}
webbrowserfinished = false;
You can try WebBrowser.DocumentCompleted Event
Occurs when the WebBrowser control finishes loading a document.
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate("google.com");
webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
MessageBox.Show("Completed Now!");
}
Well it isn't the best of solutions but you could always start a timer when the web browser navigates, and set timer1.Tick to something like 3000, then within the timer1_Tick method you can do your calculations on the new page, and then timer1.Stop();.
There is probably a better solution using events but I'm not too good with web browsers myself.
You can use Thread.sleep(5000) to wait for your page to load, because if you don't, the navigate method will load a new doc into web browser control but it will not call document_complete_event_handler

Handling an event on a dynamically-added Button after postback

Basically, I have an update panel in which i have a link button, when user clicks on the link button all the contents are cleared and textbox shows up in which user enters something and when user hit enter key, the update panel should be refreshed or gets updated or repopulated with all the contents .
How can I do it ???
The way I am trying to do this is that when event handler of link button is fired, I created a hidden button dynamically and assign it a new event handler which will get fired when user hits enter key.This new dynamic button is created inside link button event handler. In this new button event handler I will repopulate the contents back.
The problem with my way is the event handler of dynamically created button is not fired.
Why ???
Please try to answer in c#.
Thanks in advance.
Regards,
My code #
protected void Submit_Click1(object sender, EventArgs e)
{
Label1.Text = TextBox1.Text + TextBox2.Text + " are sucessfully registered";
Button mento = new Button();
mento.cssclass = "invisible";
mento.Click += new EventHandler(mento_click);
// here this new mento button is attached to update panel
updatepanel1.ContentTemplateContainer.Controls.add(mento);
}
Now the problem is mento_click event handler does not get fired ???
You can catch the enter key, in the textbox?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//add event keydown
textBox1.KeyDown += new KeyEventHandler(textBox1_KeyDown);
}
void textBox1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode )
{
case Keys.Enter:
//YOur updatecode here:
MessageBox.Show("You press enter");
break;
default:
break;
}
}
}
You have to attach the event on page_init or page_load every time theres a request, or the event wont get hooked up to the control.
you can check out this link to understand why:
http://msdn.microsoft.com/en-us/library/ms178472.aspx
Example
if you want to hook it up on the submit you should do something like:
page_init(object sender, EventArgs e)
{
CreateControls();
}
private void CreateControls()
{
//Create button with event and add to the panel
}
clickEvent(object sender, EventArgs e)
{
updatePanel.Update();
}
That should fire correctly the event. Im sorry i just wrote this on the fly and didnt test it, but i hope it gives you de general idea.
Cheers.
To all of you strugling with postback from buttons in asp.net, I would like to mention an alternative and ancient method of dealing with button-click events.
1) name your dynamically created buttons using a Prefix (like for instance this one: btn_). That way, every button you create will have a name starting with this prefix. For example the first button you create will have the name btn_0. You can achieve this by a routine like this one:
For _counter As Integer = 0 To 3
Dim butt As New Button
' the next 1 line is convenient when programming for the .net 4.0 framework:
butt.ClientIDMode = UI.ClientIDMode.Static
butt.butt.ID = "btn_" & _counter
butt.Text = "someting"
page.controls.add(butt)
next
2) ... and then, to handle it all, you can do it like this in the on_load event of your asp.net page:
If IsPostBack Then
For Each key As String In Request.Form
If InStr(Trim(key), "btn_") > 0 Then
Response.Write(Request.Form(key))
End If
Next
End If

Categories

Resources