I am performing a validation for my ID field when the user chooses what format it will be. The validation works except for the fact that when it displays the messagebox you select OK, then it repeats once more before going back to the form. I have supplied my code for it below. I used the dialogresult part to see if making it perform an action would stop the problem. This was fixed by using the Click event as mentioned by one of the answers.
private void rChkBoxB_ToggleStateChanged(object sender, Telerik.WinControls.UI.StateChangedEventArgs args)
{
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
}
}
}
The new problem is turning the checkbox back to false after the click event. Here is my updated code. The typical checkbox.checked = false does not change it back to false. I used breakpoint to verify I am getting the to the if statement and the value says false for my checkbox. How can I change the property back to false?
private void rChkBoxB_Click(object sender, EventArgs e)
{
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
}
}
}
Because you've set Checked = false in return of the dialogresult? Hence, toggling the state again?
EDIT: Of note, you are probably using the CheckStateChanged event. So, you check the checkbox (setting it to true), it fires, you show the MessageBox, you set the checkbox back to false, which in turn, causes the event to fire again (you are changing the state).
This is where you could use the Click event, as opposed to setting a flag (proposed solution). That way when you set the checkbox back to false, in code, the Click event won't fire. At runtime, a Click event, for a checkbox, will always toggle the checkbox on/off, no matter where you click on the checkbox.
In conclusion, just use the Click event:
private void rChkBoxB_Click(object sender, EventArgs e)
{
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
}
}
}
Of course, in either version of your code, I'm assuming you want to actually check if Text > 256 when you are checking it to true. So you might want to:
private void rChkBoxB_Click(object sender, EventArgs e)
{
if (rChkBoxB.Checked == false) return; // NEW CODE HERE
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
}
}
}
The code is not the problem, but the event ToggleStateChanged being called more than one time when rChkBoxB.Checked = false;
It run two times because you change the checked property inside the radio button. When you change it the CIL see that it generate a new flag and it does again the event.
For anticipating this you can put a second control in the first if
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256 && rChkBoxB.Checked)
{
///TODO
}
I also suggest to check if the input is correct: in this case you want only int so you can use int.TryParse(string, out int) (see reference here) or you can use Regex (references here)
Problem: ToggleStateChanged event will be fired whenever Checkbox state is being changed. Your checkbox state is getting changed when you set rChkBoxB.Checked = false; that is the reason why your ToggleStateChanged event is invoking twice.
Solution: Take a bool variable and make it true when user selects ok , then even if the ToggleStateChanged event triggers it wont invoke the function twice as isValid is set to true.
bool isValid=false;//declare as class variable
private void rChkBoxB_ToggleStateChanged(object sender, Telerik.WinControls.UI.StateChangedEventArgs args)
{
if(!isValid)
{
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
isValid=true;
}
else
{
isValid=false;
}
}
}
else
{
isValid=false;
}
}
Related
I have a click event that I run when someone selects a checkbox. I have provided my code below as a reference. The checkbox does not clear after the user selects OK. I clearly set the property to false in the code, and I used breakpoint to make sure it was getting to that point and it was. I even made sure my checkbox was receiving false and it was. What is preventing me from unchecking that box and how should I go about fixing this problem?
private void rChkBoxB_Click(object sender, EventArgs e)
{
if (Convert.ToInt32(rTxtBoxFormatID.Text) > 256)
{
DialogResult dialogresult = MessageBox.Show("B does not support numbering over a number!", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
if (dialogresult == DialogResult.OK)
{
rChkBoxB.Checked = false;
}
}
}
Can you try executing this code on MouseUp instead of Click
I've got a DataGridView with bound data, but there is a checkbox column that is unbound that I am keeping track of myself. The EditMode is EditProgrammatically. When the user tries to Disable the checkbox, I pop a message box asking them if they are sure they want to disable it. If they choose yes, I disable it. No, I cancel the edit. When they choose yes and I change the value, the message box fires again. Anyone have any idea why this is happening?
Here is the code in question:
private void dgv1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
if (dgv1.BeginEdit(false))
dgv1.EndEdit();
}
private void dgv1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
if (dgv1.Columns[e.ColumnIndex].Name == "Enabled")
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)dgv1.Rows[e.RowIndex].Cells["Enabled"];
if (checkCell.Value.Equals(checkCell.FalseValue))
{
checkCell.Value = checkCell.TrueValue;
}
else
{
DialogResult result = MessageBox.Show(this, "Are you sure you want to Disable this?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
if (result == DialogResult.No)
e.Cancel = true;
else
checkCell.Value = checkCell.FalseValue;
}
}
private void dgv1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
dgv1.CommitEdit(DataGridViewDataErrorContexts.Commit);
}
i am not sure why this is happening, maybe you can just show the messagebox on CurrentCellDirtyStateChanged and then call the dgv1.CancelEdit() or CommitEdit() method.
i had a similar situation, where i had to execute code after a checkboxcell changed its value. You can use this code to uncheck it after it was checked.
This way the value is set to true by default checkbox functionality and later you set it back to false if not confirmed. so this is kind of dirty but should work.
void dgv1_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if (dgv1.Columns[e.ColumnIndex].Name == "Enabled")
{
DataGridViewCheckBoxCell checkCell = (DataGridViewCheckBoxCell)dgv1.Rows[e.RowIndex].Cells["Enabled"];
if(!checkCell.Checked)
{
DialogResult result = MessageBox.Show(this, "Are you sure you want to Disable this?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2);
if (result == DialogResult.No)
{
checkCell.Value = checkCell.TrueValue;
}
}
}
}
the CellValueChanged event is prolly fired too late (as soon as the cell focus is lost). therefore Commit your changes in CellDirtyStateChanged
void dgv1_CurrentCellDirtyStateChanged(object sender, EventArgs e)
{
if (dgv1.IsCurrentCellDirty && dgv1.CurrentCell.ColumnIndex == dgv1.Columns["Enabled"].Index)
{
dgv1.CommitEdit(DataGridViewDataErrorContexts.Commit); // raises the cellvaluechangedevent for checkboxes and comboboxes
}
}
I have a login form and a button which check if the user name and the password are true.
but the problem is the code I tried .. I must click on the connect button twice.
but the code should work when I click on the button just once ! Right ?
I think the problem is: the showDialog won't be disappeared if only I click in some button that it's DialogResult set in some value, so in the first click the connexionButton.DialogResult gets the DialogResult.OK value and in the second click the button executes the code.
*you can notice that the event simpleButton1_Click is the event for the connexionButton Button*
this is the event I used :
this.connexionButton.Click += new System.EventHandler(this.simpleButton1_Click);
this is the code I tried :
private void simpleButton1_Click(object sender, EventArgs e)
{
Boolean allowCnx = false;
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
{
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
{
allowCnx = true;
}
}
if (allowCnx)
{
connexionButton.DialogResult = DialogResult.OK;
}
else
XtraMessageBox.Show("Invalide Information", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
and this is the code I used to call this login form :
using (login loginForm = new login())
{
var result = loginForm.ShowDialog();
if (result == DialogResult.OK)
this.Show();
else
this.Close();
}
// Points to a different method than the one you posted
// (simpleButton1_Click_1 instead of simpleButton1_Click)
this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click_1);
// This isn't simpleButton1_Click_1
private void simpleButton1_Click(object sender, EventArgs e)
Not sure if that is your issue, but it looks like your event handler is a different method than the one you posted. Do you have another method called simpleButton1_Click_1 somewhere in your code and you've just gotten slightly confused?
EDIT: In response to your changes/additions
You seem to have some confusion over ShowDialog and DialogResult.
// When you launch the login form, I do not know what you intended to do with your
// calls to Show() and Close() but so long as you don't instend for them to do
// anything to the loginForm, that's fine.
using (login loginForm = new login())
{
if (loginForm.ShowDialog() == DialogResult.OK)
// Do stuff if logged in
else
// Do stuff if failed
}
private void simpleButton1_Click(object sender, EventArgs e)
{
Boolean allowCnx = false;
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
{
allowCnx = true;
}
if (allowCnx)
{
this.DialogResult = DialogResult.OK; // Don't set the DialogResult of a button. Set it for the form.
}
else
{
this.DialogResult = DialogResult.Abort; // Because we didn't succeed
XtraMessageBox.Show("Invalide Information",
"Erreur",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
You are using simpleButton1_Click_1 instead of simpleButton1_Click.
Infact the code should be:
this.simpleButton1.Click += new System.EventHandler(this.simpleButton1_Click);
EDIT :
yes I just forgot when I copied the event.. I mean
this.connexionButton.Click += new
System.EventHandler(this.simpleButton1_Click);
I think, in this case, you should use a bool instead of a DialogResult, so try:
public bool AllowConnection = false;
private void simpleButton1_Click(object sender, EventArgs e)
{
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
{
if (row[1].ToString().ToLower() == idBox.Text.ToLower() && row[2].ToString().ToLower() == mdpBox.Text.ToLower())
AllowConnection = true;
}
if (!AllowConnection)
XtraMessageBox.Show("Invalide Information", "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
And:
using (login loginForm = new login())
{
loginForm.ShowDialog();
if (loginForm.AllowConnection)
this.Show();
else
this.Close();
}
Change your iterator for your rows from AsEnumerable to Rows.
FROM:
foreach (var row in myClass.ds.Tables["Users"].AsEnumerable())
TO:
foreach (var row in myClass.ds.Tables["Users"].Rows)
This may sound odd, but if there is any change to that table, anywhere, while you are iterating through your enumerable it will break your iteration. See DataTableExtensions.AsEnumerable This could be perhaps another process accessing this table at the same time, or using a datareader that has not completed filling the table in before the iteration starts.
Also, try to change your code to access the form's dialog result directly, instead of through the button.
FROM:
connexionButton.DialogResult = DialogResult.OK;
TO:
this.DialogResult = DialogResult.OK;
Your code should only set that if your boolean value is set to true, so you will not be closing the form if your checks are correct.
You need to set the Form.DialogResult to DialogResult.OK, not the DialogResult of the Button.
Some Code:
this.DialogResult = DialogResult.OK
Some Additional Thoughts:
It's clearly better to build a standalone method to check for
existence of the user. Don't do this in the ClickEvent. Maybe you need this method again and then you will rewrite this. This will only produce bloated code.
Prevent Users from clicking the Button before Textboxes are filled with values.
private void mnuCustomerAdd_Click(object sender, EventArgs e)
{
CustomerForm frmCust = new CustomerForm("Add A New Customer");
int index = lstCustomers.SelectedIndex;
if (index != -1)
frmCust.CustomerData = new Customer(customerMngr.GetCustomer(index).ContactData);
MessageBox.Show("dev1");
DialogResult dr = frmCust.ShowDialog();
if (dr == DialogResult.OK)
{
MessageBox.Show("dev2");
if (frmCust.ReadInput())
{
MessageBox.Show("dev3");
customerMngr.AddCustomer(frmCust.CustomerData);
}
else
MessageBox.Show("Please supply all necessary fields with the correct information");
}
UpdateCustomerList();
}
Don't understand what I'm doing wrong here, I want to execute the conditional statements if the user hits OK in the Form that appears at frmCust.ShowDialog().
At the moment I can only get to "dev1".
Perhaps your dialog isn't setting the dialog result. Make sure your OK and Cancel buttons have their DialogResult properties set to what you expect.
Be sure correctly assign DialogResult property of the Form before it closed.
So it will be returned like a return value of ShowDilaog() call.
There is another option too, is use AcceptButton and CancelButton, in order to handle corresponding Enter and Cancel keypress.
Place a Breakpoint (F9) on the line:
if (dr == DialogResult.OK)
When the dialog closes you will have chance to examine what dr is set to.
To get the Dialog to return DialogResult.OK you can either set it in the OK button of the Dialog:
void buttonOK_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.OK;
Close();
}
Or you can do the option in Tigran's answer.
I have a Windows forms application in C# and I have a form that when the user closes it I ask, "do you want to save the changes"? How can I get the changes in my form? Here is some code:
public partial class DepartEdit : Form
{
string _nameDep; //This variavel get value textbox when form load
{
InitializeComponent();
}
private void DepartamentEdit_FormClosing(object sender, FormClosingEventArgs e)
{
if (txtNameDepart.Text != _nameDep && codDepartament > 0)//Here i compare
{
DialogResult dlg = MessageBox.Show("Save changes?", "Question", MessageBoxButtons.YesNo);
if (dlg == DialogResult.Yes)
{
saveDepart(); // Metod save depart
e.Cancel = false;
}
if(dlg ==DialogResult.No)
{
e.Cancel = false;
}
}
}
There are a lot of textboxs and combo boxes? Is there any other way to get the changes in the form?
A lot will depending on where the information is held.
It you are using DataBinding you should be just monitoring the listChanged event or calling dataTable.GetChanges() if you are using a DataTable.
If the information comes from a class the implements ICloneable and IComparable, then you can take just take a backup copy when intialising the form (and after saving) and when closing you prepare you class for saving and compare it with the original.
Otherwise you can do something like
Declare a private variable
private bool requiresSaving =false;
Declare an event
private void SomethingChanged(object sender, EventArgs e)
{
requiresSaving = true;
}
Hook up this event to the various changed events, eg
this.txtNameDepart.TextChanged += new System.EventHandler(this.SomethingChanged);
(The actual event is sometimes called something different , eg ValueChanged, SelectedIndexChanged , but they can all point to SomethingChanged unless you need a particular event to do something else.)
Check this variable when you are closing the form
private void DepartamentEdit_FormClosing(object sender, FormClosingEventArgs e)
{
if (requiresSaving)
{
....
You also need to set requiresSaving false in the saveDepart method.
Alternatively I have seem code where, when the control is being intialised, the tag value is also set, and the formclosing event loops through each control and compares the original values (in the tag object) with the current values.
Create a string (or string[] I guess) within the Form_Load event and initialise them with the values present when the form first opens.
eg
string oName = nameTextBox.Text;
string oCompany = companyComboBox.Text;
Then during the Form_Closing() event you can check these against the current values
private void Contact_FormClosing(object sender, FormClosingEventArgs e)
{
if (oName!=nameTextBox.Text||oCompany!=companyComboBox.Text)
{
DialogResult result = MessageBox.Show("Would you like to save your changes",
"Save?",
MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Stop);
if (result == DialogResult.Yes)
{
SaveFormValues();
}
else if (result == DialogResult.Cancel)
{
// Stop the closing and return to the form
e.Cancel = true;
}
else
{
this.Close();
}
}
}
Loop the forms controls, and add your event watchers. These events will call a function in the form that will keep a Hashtable or some other various collection up to date w/ the status of any changes to a particular control.
like I have, Hashtable changes;
then each time my event is called, i say, Add Control.Name, and then a change status, whatever you want. Then you have a list of controls that have been updated.
I can go into more detail if need be, hopefully this will get you started.
Well I think the theory is good. There are some problems with the implementation.
if (dlg == DialogResult.Yes)
{
saveDepart(); // Metod save depart
e.Cancel = false;
}
if(dlg ==DialogResult.No)
{
e.Cancel = false;
}
I think it would be a lot similier to write this:
if(dlg == DialogResult.Yes)
{
saveDepart();
}
// You don't need to change e.Cancel to false here unless you set it to true previously.
It's simple
Declare a global variable count=0
Now on your form u might already have a Save button so just increment count on save button click event
Now on form close event just check for the value of count if it's 0 ask user to save info either by reminding by message box
If it's 1 or greater than1 just close the form
I hope u get it