Stopping Button Click Function in C# Winfoms - c#

I have a Save Button that grabs information and stores it in SQL from a Winform.
The issue I'm having is that if you click the save button, it still stores blank information in the database. I don't want this. Here's my code. Keep in mind, the actual saving, updating, getting data work perfectly.
private void btnSave_Click(object sender, EventArgs e)
{
if (txtLocalSourcePath.Text != null)
{
if (ResourceKey == 0)
{
ConnString = ConfigurationManager.ConnectionStrings["Dev"].ConnectionString;
GetData(ConnString);
InsertData(ConnString);
GetData(ConnString);
lblInsertNewRecord.Visible = true;
lblInsertNewRecord.Text = String.Format("You have inserted a new record at {0}", System.DateTime.Now);
}
else
{
UpdateData();
GetData(ConnString);
lblInsertNewRecord.Visible = true;
lblInsertNewRecord.Text = String.Format("Updated Record at {0}", System.DateTime.Now );
}
ClearData();
}
else
{
lblInsertNewRecord.Visible = true;
lblInsertNewRecord.Text = "Cannot add record. Please select file.";
}
}
I have tried these options:
stopping a function executed on a winform button click
How to cancel any event in winforms?
How to cancel winform button click event?

You probably want to try if (txtLocalSourcePath.Text != null && txtLocalSourcePath.Text.Length > 0), or the solution proposed by basher:
if (!string.IsNullOrEmpty(txtLocalSourcePath.Text))
The .Text property is NOT actually null, but instead just a blank ("") string.
Edit: Russ Wilson's recommendation in comments is also handy: if (!string.IsNullOrWhiteSpace(txtLocalSourcePath.Text)), which guarantees that the string is not just spaces/tabs/etc.

Related

RepositoryItemLookupEdit new value disappears before being processed

I have a LookupEdit in the grid that needs to be able to accept new values. When I enter the new value and press "Enter" or "Tab", it saves normally via the ProcessNewValue event, however when I enter a value and click elsewhere in the grid, on another cell or just in white space, the value vanishes completely. By implementing several other events and setting breakpoints all I figured out was that the value disappears before the "CloseUp" event fires. Validating, EditValueChanged, EditValueChanging, ProcessNewValue, Closed, Leave, and even GetNotInListValue never even get called because of the empty value.
Can anyone think of some setting I haven't found yet, or any other reason why this value would disappear...And how I might stop it from happening?
Found a valid Workaround
I implemented the following 3 events, in sequence, to solve this issue. I still have no idea what caused it, or how to go about preventing it. This is a Workaround, not a solution, and should be treated as such. I end up having to manually call the ProcessNewValue method, as well as forcing the value to equal the text field, and the text field back into the value later on. Not the smoothest of operations, but it does work.
private void repPatchNum1_EditValueChanging(object sender, DevExpress.XtraEditors.Controls.ChangingEventArgs e)
{
string surfaceSoftware = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "SurfaceSoftware");
if (string.Compare(surfaceSoftware, SOFTWARE_CHECK, true) == 0)
{
string version = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "Version");
if (version.ToLower().Contains(VERSION_CHECK))
{//now we are certain we are in the right place
LookUpEdit editor = sender as LookUpEdit;
if (!((RPickListCollection)((BindingSource)editor.Properties.DataSource).DataSource).OfType<RPickList>().Any(a => a.RValue.Equals(e.NewValue)))
{
repPatchNum1_ProcessNewValue(sender, new DevExpress.XtraEditors.Controls.ProcessNewValueEventArgs(e.NewValue));
vwSurfaceSoftware.SetRowCellValue(vwSurfaceSoftware.FocusedRowHandle, colPatchNum, e.NewValue);
}
}
}
}
private void repPatchNum1_CloseUp(object sender, DevExpress.XtraEditors.Controls.CloseUpEventArgs e)
{
string surfaceSoftware = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "SurfaceSoftware");
if (string.Compare(surfaceSoftware, SOFTWARE_CHECK, true) == 0)
{
string version = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "Version");
if (version.ToLower().Contains(VERSION_CHECK))
{//now we are certain we are in the right place
LookUpEdit editor = sender as LookUpEdit;
if (!((RPickListCollection)((BindingSource)editor.Properties.DataSource).DataSource).OfType<RPickList>().Any(a => a.RValue.Equals(e.Value)))
{
e.Value = ((LookUpEdit)sender).Text;
}
}
}
}
private void repPatchNum1_Closed(object sender, DevExpress.XtraEditors.Controls.ClosedEventArgs e)
{
string surfaceSoftware = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "SurfaceSoftware");
if (string.Compare(surfaceSoftware, SOFTWARE_CHECK, true) == 0)
{
string version = vwSurfaceSoftware.GetRowCellDisplayText(vwSurfaceSoftware.FocusedRowHandle, "Version");
if (version.ToLower().Contains(VERSION_CHECK))
{//now we are certain we are in the right place
LookUpEdit editor = sender as LookUpEdit;
string patch = vwSurfaceSoftware.GetRowCellValue(vwSurfaceSoftware.FocusedRowHandle, colPatchNum).ToString();
if (String.IsNullOrEmpty(editor.Text) && !String.IsNullOrEmpty(patch))
{
editor.Text = vwSurfaceSoftware.GetRowCellValue(vwSurfaceSoftware.FocusedRowHandle, colPatchNum).ToString();
vwSurfaceSoftware.UpdateCurrentRow();
}
}
}
}
As to the original question: Please post an answer if you know why this might be happening or how to prevent it.
Thanks all :-)
I think I found a simpler workaround, tested on DevExpress 13.
When user presses Tab/Enter, event sequence is ProcessNewValue -> CloseUp
However if user finishes lookup by clicking somewhere else, events are reversed: CloseUp -> ProcessNewValue and entered value is lost. We can use PopupCloseMode.Immediate (specifies that the dropdown window was closed because an end-user clicked outside the editor) to detect this case, manually take entered value from editor, set it to event Value field and manually call ProcessNewValue. No need for other events.
private void myLookUp_CloseUp( object sender, CloseUpEventArgs e )
{
var lookUpEdit = sender as LookUpEdit;
if( lookUpEdit != null )
{
var enteredLookUpText = lookUpEdit.Text;
if( e.CloseMode == PopupCloseMode.Immediate )
{
e.Value = enteredLookUpText;
myLookUp_ProcessNewValue( sender, new ProcessNewValueEventArgs( enteredLookUpText ) );
}
}
// Rest of event handler
}

c# : Create a connect button

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.

Messagebox.Show raises combo box SelectedIndex/Value Changed Events?

Consider a form with a dataGridView bound to a strongly typed dataset. A combo box exists on the top to allow the user to select an employee. Once selected, the gataGridView's dataset is filled based on the employee's ID.
Some data entry is done on the dataGridView and once completed the user saves. In order to keep the user from accidently moving to another employee and deleting what they keyed, I prompt them to save is the dataset HasChanges() is true.
I was catching this piece of code in the SelectedIndexChanged event of the combo box but this also raises the event in the SelectedValueChanged
private void checkSaveChanges()
{
this.Validate();
this.laborTicketBindingSource.EndEdit();
if (dP_LaborTicket.HasChanges())
{
DialogResult result = MessageBox.Show("Do you want to save your changes?", "Save before closing?", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
if (result == DialogResult.Yes)
this.tableAdapterManager.UpdateAll(this.dP_LaborTicket);
}
}
Here is a snippet of the event that gets raised:
private void cmbEmployeeID_SelectedIndexChanged(object sender, EventArgs e)
{
checkSaveChanges();
if (cmbTransactionDate != null && cmbEmployeeID.SelectedValue != null)
{
string selectedDate = cmbTransactionDate.Value.ToString("MM/dd/yyyy");
string selectedEmployee = cmbEmployeeID.SelectedValue.ToString();
this.laborTicketTableAdapter.Fill(this.dP_LaborTicket.LaborTicket, selectedEmployee, selectedDate);
}
}
So stepping into this once I change a record and move to another employee, it steps into checkSaveChanges. Successfully validates and ends the edit and checks if it has changes (which it does).
After executing MessageBox.Show, the program is suddenly sent back to the cmbEmployeeID_SelectedIndexChanged event, where it calls checkSaveChanges yet again. This only happens twice though, and even if they say yes or no, the code within the prompting block runs.
How in the world is MessageBox.Show calling this twice? If I comment that line out this does not happen...
EDIT
As a bonus piece of information, the combo box AutoCompleteMode was set to SuggestAppend (Shows a dropdown as your typing) and DropDownStyle is set to DropDownList.
I changed the AutoCompleteMode to Append and this doesn't happen anymore, it seems to only happen with the SuggestAppend Mode...
I think Sven could be right that the MessageBox.Show will cause the dropdown to loose focus.
One way to work around this problem could be to detect if the event is already executing using a private boolean in the class. You'd then get something like this:
private bool fIsInEvent = false;
private void cmbEmployeeID_SelectedIndexChanged(object sender, EventArgs e)
{
if (!fIsInEvent)
{
fIsInEvent = true;
try
{
// your code
}
finally { fIsInEvent = false; }
}
}

Cancelling ListBox SelectedIndexChange Event

Is it possible to cancel the SelectedIndexChange event for a listbox on a winforms application? This seems like such a logical thing to have that I must be overlooking some easy feature. Basically, I have been popping up a message box asking if the user really wants to move to another item, as this will change the UI and I don't want their changes to be lost. I'd like to be able to cancel the event in case the user has not saved what they are working on. Is there a better way of doing this?
You cannot cancel it.
What I did just a couple of days ago was to have a variable with the latest selected index. Then when the event fires, you ask the user if he wants to save, this is done in the eventhandler. If the user selected "Cancel" you change the id again.
The problem is that this will make the event fire once again. So what i've used is a bool just saying "Inhibit". And at the top of the eventhandler I have:
if(Inhibit)
return;
Then below this where you ask the question you do something like this:
DialogResult result = MessageBox.Show("yadadadad", yadada cancel etc);
if(result == DialogResult.Cancel){
Inhibit = true; //Make sure that the event does not fire again
list.SelectedIndex = LastSelectedIndex; //your variable
Inhibit = false; //Enable the event again
}
LastSelectedIndex = list.SelectedIndex; // Save latest index.
This is exactly #Oskar Kjellin 's method, but with a twist. That is, one variable less and with a selected index changed event that really behaves like a selected index changed event. I often wonder why is selected index changed event getting fired even if I click on the exact same selected item. Here it doesn't. Yes it's a deviation, so be doubly sure if you want this to be there.
int _selIndex = -1;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listBox1.SelectedIndex == _selIndex)
return;
if (MessageBox.Show("") == DialogResult.Cancel)
{
listBox1.SelectedIndex = _selIndex;
return;
}
_selIndex = listBox1.SelectedIndex;
// and the remaining part of the code, what needs to happen when selected index changed happens
}
I just ran into this exact problem. What I did is when the user makes changes, I set ListBox.Enabled = false; This disallows them to select a different index. Once they either save or discard their changes, I set ListBox.Enabled = true; Probably not as slick as a prompt, but it gets the job done.
More elegant, use the Tag property:
if ((int)comboBox.Tag == comboBox.SelectedIndex)
{
// Do Nothing
}
else
{
if (MessageBox.Show("") == DialogResult.Cancel)
{
comboBox.SelectedIndex = (int)comboBox.Tag;
}
else
{
// Reset the Tag
comboBox.Tag = comboBox.SelectedIndex;
// Do what you have to
}
}
The SelectedIndexChanged cannot be cancelled. So you only have one real option:
private int? currentIndex;
public void ListBox_SelectedIndexChanged(sender, EventArgs args) {
if (currentIndex.HasValue && currentIndex.Value != listBox1.SelectedIndex) {
var res = MessageBox.Show("Do you want to cancel edits?", "Cancel Edits", MessageBoxButtons.YesNo);
if (res == DialogResult.Yes) {
currentIndex = (listBox1.SelectedIndex == -1 ? null : (int?) listBox1.SelectedIndex);
} else {
listBox1.SelectedIndex = currentIndex.Value;
}
}
}
This is my way to cancel SelectionChange for ComboBox. I think it could also fit to ListBox.
private bool comboBox_CancelSelection = false;
private int comboBox_LastSelectedIndex = -1;
private void comboBox_SelectedIndexChanged(object sender, EventArgs e) {
if (comboBox_CancelSelection) {
comboBox_CancelSelection = false;
return ;
}
// Handle Event
if (!comoBox_CancelSelection) {
comboBox_LastSelectedIndex = comboBox.SelectedIndex;
} else {
comboBox.SelectedIndex = comboBox_LastSelectedIndex;
}
}

Form closing save changes before close

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

Categories