I want to validate winform using error provider. When user click on button multiple Validated methods are executed txtFieldOne_Validated(this, e); txtFieldTwo_Validated(this, e); and I need solution to stop execution further if any of this validators fails and display error using error provider.
I thought to use private variable bool _formValid like
private btnValidateFields_Click(object sender, EventArgs e)
{
txtFieldOne_Validated(this, e);
txtFieldTwo_Validated(this, e);
if(_formValid)
{continue...}
}
private void txtFieldOne_Validated(object sender, EventArgs e)
{
if(....)
errorProvider1.SetError(txtFieldOne, "some error message")
_formValid = true;
else(....)
errorProvider1.SetError(txtFieldOne, "")
formValid = false;
}
but using this approach if last checked field was true than populated _formValid remains true and form pass.
I am not clear what you are trying to do. But as per your comments, I will suggest something like this.There is no need to call different Validation method for different controls. All controls should be validated in same method.
void IsFormValid(this, e)
{
bool result = ValidateAllControls();
if(!result)
return;
// Rest of the execution
}
bool ValidateAllControls()
{
if(!control1.IsValid)
return false;
if(!control2.IsValid)
return false;
if(!control3.IsValid)
return false;
return true;
}
Let me know if I misunderstood something.
Hope it helps.
Related
Sorry, this may be a duplicate question, but I couldnot understand the solutions already provided in different answers.
I have created a mp3 player in a different manner, it plays one mp3 file at a time but one listbox have the chapters, which is not only handling to move position of that particular mp3 but also changes a picturebox image. Now somewhere I need to change the selection of the listbox from a seekbar but dont want to fire the following event of;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
Please guide.
One way to inhibit your selection indexed change event doing its normal way is to use a boolean flag. Also, make sure that this inhibition does not stay around when some exception is raised:
private bool inhibit = true;
private void doSomeProcessWithInhibit()
{
try
{
inhibit = true;
// processing comes here
}
// if something goes wrong, make sure other functionality is not blocked
finally
{
inhibit = false;
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
// fast return to reduce nesting
if (inhibit)
return;
// do event handling stuff here
}
P.S. Try to use meaningful names for controls (check listBox1). You will thank yourself when revisiting the code and/or others have to.
Add a Boolean with class scope called something like isProcessing. Set it to true. Do your work, then set it to false. Warp your event in the Boolean:
bool isProcessing = true;
private void switchControls(){
isProcessing = true;
//do work;
isProcessing = false;
}
private void MyControl.OnEvent(object sender, EventArgs e){
if(!isProcessing){
//what you would normally do
}
}
OR....
Deregister the event, the re-register it
private void switchControls(){
myButton1.OnClick -= myButtonClick;
//do work
myButton1.OnClick += myButtonClick;
}
I have a form with two text fields, A and B that are supposed to behave in the following way:
Typing something into A should set B.Text = f(A.Text)
Typing something into B should set A.Text = g(B.Text)
...for some arbitrary and potentially unrelated functions f and g.
The problem I'm facing is that the naive implementation of simply throwing the above code into each field's handler will create an infinite loop as A's handler will update B's value and call B's handler, which will update A, etc.
What would be the correct (and preferably thread-safe) way to handle this? Either somehow determining whether a change was done manually or programmatically, somehow suppressing events firing when changing the value, or some other way.
Use a flag to signal that you are doing changes
private bool updating;
private void A_TextChanged(object sender, EventArgs e)
{
if (!updating) {
updating = true;
B.Text = f(A.Text);
updating = false;
}
}
private void B_TextChanged(object sender, EventArgs e)
{
if (!updating) {
updating = true;
A.Text = g(B.Text);
updating = false;
}
}
You don't have to care about thread-safety as this all happens in the unique UI-thread. UI events never create new threads; i.e. an event (click, text changed, etc.) never interrupts another one!
If you want to be sure that the flag is reset, you can use the try-finally statement. The finally block is ensured to run, even if an exception should occur within the try block (unless the application is terminated unexpectedly).
if (!updating) {
updating = true;
try {
A.Text = f(B.Text);
} finally {
updating = false;
}
}
I assume you're using TextChanged event, try this then:
private bool callB=true;
private bool callA=false;
private void A_Click(object sender, System.EventArgs e)
{
callB=true;
callA=false;
}
private void B_Click(object sender, System.EventArgs e)
{
callB=false;
callA=true;
}
private void A_textchanged(object sender, RoutedEventArgs e)
{
if(callB)
B.text=f(A.text);
}
private void B_textchanged(object sender, RoutedEventArgs e)
{
if(callA)
A.text=g(B.text);
}
Anyway, a better way to just edit A when the user is finished with B(finished whatever he wanted to write in it), that's because if expression will be evaluated at every character the user inputs.
By the way, changing a text while the user writes might be surprising to him, so better to avoid textchanged event in this case.
I am trying to validate textboxes for empty values. If the textbox is empty and loses focus, an error has to show and the textbox has to receive focus again.
Reading about this I came across the Validating event, which can be cancelled through e.Cancel. However when I try to do this, I get an error message.
My code:
private void CheckInput(CancelEventArgs e, TextBox tb)
{
ErrorProvider error = new ErrorProvider();
if (!string.IsNullOrEmpty(tb.Text))
{
error.SetError(tb, "*");
e.Cancel = true;
}
else
{
error.SetError(tb, "");
}
}
private void tbTitel_Validated(object sender, CancelEventArgs e)
{
CheckInput(e, tbTitel);
}
And the error I get is the following:
Error 1 No overload for 'tbTitel_Validated' matches delegate 'System.EventHandler'
How can I fix this?
The validating uses this delegate:
private void tbTitel_Validating(object sender, CancelEventArgs e)
{
}
The validated event uses this:
private void tbTitel_Validated(object sender, EventArgs e)
{
}
You want to use the Validating event (you should link you eventhandler to the validating event, not the validated event. This way you can cancel it.
You probably clicked the validating first and copy/paste/selected the eventhandler name into the validated event. (designer)
The error occurs, because tbTitel_Validated doesnt have CancelEventArgs in its signature.
Take a look at this thread for further information:
No overload for 'method' matches delegate 'System.EventHandler'
Conclusion: Use tbTitel_Validating instead.
You should use the Validating event to execute your checks, not the Validated event.
The two events have different signatures. The Validated event receives the simple EventArgs argument, while the Validating event receives the CancelEventArgs argument that could be used to revert the focus switch.
Said that, it seems that your logic is wrong.
// error if string is null or empty
// if (!string.IsNullOrEmpty(tb.Text))
if (string.IsNullOrEmpty(tb.Text))
{
error.SetError(tb, "*");
e.Cancel = true;
}
else
{
error.SetError(tb, "");
}
Alwasy use validation statements at Object.Validated event handler
Likewise:
private void textBox1_Validated(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox1.Text) || textBox1.Text == "")
{
MessageBox.Show("Please use valid data input!!");
}
}
I want to do something after the document have completely load... I dont want to use WebBrowser.DocumentCompleted Event, so please don't suggest me this.
I tried 2 ways to do it but they not work. Can someone tell me what I doing wrong?
Example 1
wb.Navigate("http://www.google.com");
while(wb.ReadyState != WebBrowserReadyState.Complete) { }
richtextdocument.Text = wb.DocumentText;
Example 2
wb.Navigate("http://www.google.com");
while(wb.isBusy == true) { }
richtextdocument.Text = wb.DocumentText;
Try to use timer to validate document load state.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void timer1_Tick(object sender, EventArgs e)
{
if(webBrowser1.ReadyState == WebBrowserReadyState.Complete)
{
timer1.Enabled = false;
richTextBox1.Text = webBrowser1.DocumentText;
}
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
webBrowser1.Navigate("http://www.google.com");
}
}
What you are dealing with here is trying to call an inherently asynchronous method synchronously.
As you mentioned in the comments to your question that the reason for not using DocumentCompleted is that you will need to use that event for other purposes, what I suggest you do is to use the DocumentCompleted event, coupled with a private class boolean flag to determine if this is the special case of DocumentCompleted or not.
private bool wbNeedsSpecialAction; //when you need to call the special case of Navigate() set this flag to true
public Form1()
{
InitializeComponent();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
}
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (wbNeedsSpecialAction)
{
richtextdocument.Text = wb.DocumentText;
wbNeedsSpecialAction = false;
}
else
{
//other cases of using DocumentCompleted...
}
}
public void Browse()
{
wbNeedsSpecialAction = true; //make sure the event is treated differently
wb.Navigate("http://www.google.com");
}
This will still allow you to control other cases within the event handler.
You must take special care to ensure that your user is not able to trigger another call to Navigate() before this 'special action' page finishes loading, otherwise it may steal the special case event. One way could be to block the UI until the page finishes loading, e.g.:
Cursor.Current = Cursors.WaitCursor;
while(wb.ReadyState != WebBrowserReadyState.Complete) {application.doevents }
I've created a public bool LogedIn; in my login.cs:
if(login successful condition)
LogedIn = true;
else
LogedIn = false
But when I access this var from another form with Login Log = new Login();
by using if(Log.LogedIn) the LogedIn variable is always false, even after successful login by the user.
Why this is not working/updating its value outside its parent form?
Updating the code:
Login.cs
public bool isLogedIn;
private void button1_Click(object sender, EventArgs e)
{
if (i>-1 && (textBox2.Text == DS.Tables[0].Rows[--i][0].ToString()))
{
this.DialogResult = DialogResult.OK;
isLogedIn = true;
}
else
{
MessageBox.Show("Invalid password supplied for username \"" + comboBox1.Text + "\"", "Login Error.....", MessageBoxButtons.OK);
isLogedIn = false;
return;
}
}
Checking for the updated value in Home.cs
private void Home_Load(object sender, EventArgs e)
{
if (Log.isLogedIn) // Always False at this position.
{
label18.ForeColor = System.Drawing.Color.Green;
submitButton.Enabled = true;
}
else
{
label18.ForeColor = System.Drawing.Color.Red;
submitButton.Enabled = false;
}
}
I've checked again... I'm not having double instance of this variable in Login.cs form.
Here's how I'm calling Login.cs form via Home.cs (main form). Hope this helps...
private void loginToolStripMenuItem_Click(object sender, EventArgs e)
{
Log.FormClosed += new FormClosedEventHandler(Log_FormClosed);
Log.ShowDialog(this);
Log.BringToFront();
}
void Log_FormClosed(object sender, FormClosedEventArgs e)
{
if (Log.isLogedIn)
{
// Something here
}
else
{
// Something here
if (Log.DialogResult == DialogResult.Cancel)
Log.Hide();
}
}
I assume you have a form called Login in your application. Ignore the rest if assumption is wrong.
You are not referring to the correct instance of the Login form. In windows application, there is a collection called Application.OpenForms. This contains all the open form instances in your application. To access the correct Login form, try this:
Application.OpenForms.OfType<Form>().Where(x => x is Login).FirstOrDefault()
Make sure you have Login form always open to perform this task. You can make use of Hide instead of Close or CloseDialog for the Login form.
If you are closing the Login form, you can create static class which is accessible from each of the forms keep the properties there.
It seems that you have more than one instance of the Login class, each one with its isLogedIn var.
It is not clear where you are instantiating Login with your Login Log = new Login(); line. Have you tried to put a breakpoint there and see how many times it gets hit?
Another thing you could do is put a breakpoint on the line where isLogedIn is set, and another one where you read it. When the setting breakpoint is hit add a watch to the instance of Login (in this case add a watch to this) and choose Make Object ID from the right click menu. Your instance will be marjked by a "#1" Then do the same for the variable Log when the reading breakpoint is hit. If the mark is different (i.e. "#2") you can be sure that you are reading something different from the variable you set before.