I have a parent form with one DataGridView and a button. When the button is clicked, it opens a child window and when closed, goes back to the parent form. I want to validate the value being inputted in a cell of the DAtaGridView. I'm using CellValidated event and showing a message box whenever it inputs an invalid value. However, when I click on the button to open the child window and close it back, the DataGridView becomes just a white box with a diagonal cross, and a NullReferenceException shows.
Does anyone know what causes this issue? If not, what's the best way to validate a value of the cell and which event to put it in?
Just setup Visual Studio as described in this article: How to: Break When an Exception is Thrown. This way, you will be able to catch this exception in the debugger, and see where its roots are.
Whenever validating a cell in a DataGridView, you should use the CellValidating event.
You can get the data using the DataGridViewCellValidatingEventArgs and set the Cancel property to True if it is invalid data. This is gonna prevent the CellValidated event from being raised and should give the focus back to the given cell.
If this doesn't help, can you provide some code and show us where the exception occured?
Related
Why does DataGridView raise CellValidating event upon simple navigation through arrow keys? How can I prevent it? Here is the key information about DataGridView state when it calls CellValidating:
EditMode = EditOnKeyStrokeOrF2
IsCurrentCellInEditMode = False
e.FormattedValue = [Same as the current value of the cell]
As you can see, user has not triggered any editing operation. He's just moving across the cells by pressing right-arrow key. One would not expect validation to occur at this point, right?
Note: Examining call stack shows that KeyDownevent triggers a CommitEdit call, which in turn raises OnCellValidating.
Like it or not, this is the way things are desigend to work. See MSDN on CellValidating:
Occurs when a cell loses input focus, enabling content validation.
And to make it complete MSDN on CellValidated:
Occurs after the cell has finished validating.
The most direct and readable solution is probably to put a line like this at the start of the CellValidating event:
if (!dataGridView1.IsCurrentCellDirty) return;
One reason for the designed behaviour could be the case where a user input is actually needed to create a valid cell value. Not your case, but still a conceivable requirement.
I have a text box on a Gridview which I'm allowing some data to be edited. When the enter key is hit, the TextChanged event happens, like I'd expect. But when i change the data and click a button, the button effect not happen. I must click the button again to fire button event. I think it happen because the grid didnot lost it focus.
How to make it possible fire the button event just in one click?
You can change your gridview element's IsTabStop property to false to gain that effect.
Also if you want to cycle with Tab you can TabNavigation="Cycle" .
Both changes are in xaml.
Not much we can do to help you here without the code itself but here are couple things you could try to debug this:
Try different browsers – it may be a browser issue
Try some client side debugging – just open console and see if anything happens when you click the button for the first time
I'm experiencing some weird behavior with the ComboBox.SelectionChangeCommitted event and am wondering if anyone has an explanation for it.
Somewhere in my event handler, I call MessageBox.Show. If I choose a new value in my ComboBox, and my code causes the MessageBox to pop up, I am seeing my selceted value get reverted back to its original value.
When debugging, I am seeing that the selected value is correct before MessageBox.Show. MessageBox.Show gives control back to the user until I click "Yes" or "No". After I have clicked one of the options, control returns to the debugger and the value of my ComboBox is reverted back to its original value before my change.
I am not programmatically setting the selected value elsewhere, so I'm at a loss as to why the value gets reverted. If the event handler does not pop the MessageBox, the selected does not get reverted.
Is it possible that the fact that I'm giving control back to the UI before I'm done handling the event has anything to do with it. If so, is there a clean way to get around it? Currently I'm capturing my selected value before I pop the MessageBox and then resetting it after, but I'd prefer to not have to resort to a "hack" to fix the issue.
The problem is likely that the act of displaying the message box causes the combo box drop-down menu to close, thus abandoning any uncommitted selection the user may have made.
It's basically the same thing as dropping down a combo box, highlighting an item in the list, and then pressing the Esc key. Notice that the highlighted item does not become the selected item because you never selected it before the combo box was dismissed. (You can try it easily yourself in the "Run" dialog.)
This is one of the many reasons why it's a bad idea to throw up message boxes all over the place (the other reasons include how visually jarring message boxes are to users, and that most of them don't even bother to read them anyway). Programmers who like to use message boxes as debugging aids are often bitten by this exact scenario when they try to debug UI code.
The solution is to either:
Defer validation until the entire form is committed/submitted, at which time you can show a message box without running the risk of abandoning any currently dropped-down combo boxes.
Find an alternative (i.e., non-modal) way of displaying the validation error. WinForms provides an ErrorProvider control that you can use for this purpose. The typical usage is showing a little warning or error icon next to the control with the invalid value; the user can hover over that icon to display a tooltip with more information about the exact error.
Or perhaps a combination of both approaches, allowing the user to get instant feedback but also ensuring that you never have to handle malformed input outside of the input form.
I was incorrect in my assumption that the subclass of ComboBox I was using did not add any relevant functionality. The issue ended up being due to a LostFocus event handler I was unaware of that caused the ComboBox to revert its value.
I could not recreate your issue using the code below which is essential what you are saying you are doing. The value in the combobox gets updated. You may get a better solution by posting the SelectionChangeCommitted code.
private void comboBox1_SelectionChangeCommitted(object sender, EventArgs e)
{
try
{
ComboBox cb = (ComboBox)sender;
string check1 = cb.Text;
MessageBox.Show("Messagebox check");
string check2 = cb.Text;
MessageBox.Show(check1 + "\n\n" + check2);
//check 1 and 2 show the old value. Once the method leaves then the value in the combobox is updated.
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I have a form with a DataGridView on it.
In this DataGridView there is a DataGridViewComboBoxColumn. When changing the value of a cell of this DataGridViewComboBoxColumn, the CellValueChanged-event is only fired when leaving the cell (for example, if I click into another cell).
The event is not fired when I change the value and then just close the form.
So, how can I save the changes (if there are any changes), if my form is simply closed?
[UPDATE]
The CellValueChanged is not fired when the form the DataGridView is on is shown through form.ShowDialog():
using (FormWithDataGridView form = new FormWithDataGridView()) {
form.ShowDialog(); // DataGridView on form fires no CellValueChanged-Event when form gets closed
}
From the community content post on the MSDN entry for ShowDialog, when you close a modal form, it is just being hidden so the calling code can still have access to the DialogResult or other properties of the form. Apparently, this is why the CellValueChanged event on the DataGridView is not firing (CellParsing and CellEndEdit events also do not get raised).
As a workaround, in the form closing event, you can remove focus from the DataGridView, which will cause the CellValueChanged event to fire if necessary. If you don't have any other controls on the form to set focus to, you can put a label on the form and give it focus.
have you tried using dataGridView1.CellParsing? This should (as I understand it) trigger even if the focus of the cell is lost due to closing the containing Form. This will only trigger if the user has changed the value of the cell.
[Edit] Now when I think about it a bit more I would try dataGridView1.CellEndEdit if I was you. That is better..[/Edit]
Ran into a similar situation myself, but with the last checkbox updated programmatically--whouldn't update unless I switched rows.
Try calling the BindingSource.EndEdit method just before you update the combobox.
For me I call the data adapter afterwards and it recognizes a change to the datagridview--so it does the work.
I have a WinForms application with a DataGridView control and a column of DataGridViewButtonCell cells within that. When I click on one of these buttons, it starts a background task, and I'd like to disable the buttons until that task completes.
I can disable the DataGridView control, but it gives no visual indication that the buttons are disabled. I want the user to see that the buttons are disabled, and to notice that the task has finished when the buttons are enabled again.
Bonus points for a method that allows me to disable the buttons individually, so I can leave one of the buttons enabled while the task runs. (Note that I can't actually give out bonus points.)
Here's the best solution I've found so far. This MSDN article gives the source code for a cell class that adds an Enabled property.
It works reasonably well, but there are two gotchas:
You have to invalidate the grid after setting the Enabled property on any cells. It shows that in the sample code, but I missed it.
It's only a visual change, setting the Enabled property doesn't actually enable or disable the button. The user can still click on it. I could check the enabled property before executing the click event, but it also seemed to be messing up the appearance when the user clicked on it. Instead, I just disabled the entire grid. That works alright for me, but I'd prefer a method that allows me to disable some buttons without disabling the entire grid.
There's a similar sample in the DataGridView FAQ.
You could give this a try:
When you click on the cell...
Check to see if the process with the current row identifier is running from a class-level list; if so, exit the cell click event.
Store the row identifier in the class-level list of running processes.
Change the button text to "Running..." or something appropriate.
Attach a basic RunWorkerCompleted event handler to your process (explained shortly).
Call backgroundWorker.RunWorkerAsync(rowIdentifier).
In the DoWork event handler...
Set e.Result = e.Argument (or create an object that will return both the argument and your desired result)
In the RunWorkerCompleted event hanlder...
Remove the row identifier from the running processes list (e.Result is the identifier).
Change the button text from "Running..." to "Ready"