I'm trying to replicate this behavior in the ColumnMappings window from SQL Management Studio:
Image Here
When you click inside a destination cell, the type changes from text
to combobox (it seems), and when you leave the cell, it takes the selected value from the combobox and changes back to textboxCell with the value included.
It does this for every cell in that column.
So, when I load the data, all the cells are textbox, and when the user enters any cell in that column, I do this:
private void dgvwMapping_CellEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.ColumnIndex == 1)
{
string txt = dgvwMapping[e.ColumnIndex, e.RowIndex].Value.ToString();
DataGridViewComboBoxCell cbbxDestination = new DataGridViewComboBoxCell() { DataSource = new List<string>(someList) };
cbbxDestination.Value = txt;
dgvwMapping[e.ColumnIndex, e.RowIndex] = cbbxDestination;
}
}
So far so good, if I change from cell to cell everything goes fine, except when I click the cell that has the coordinates [1,1]. The only one that throws the "Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore" exception is the one with the columnIndex equal to the rowIndex.
I already tried wrapping the line where I reassign the Cell Type in an invoke call, like this:
dgvwMapping.BeginInvoke(new MethodInvoker(delegate ()
{
dgvwMapping[e.ColumnIndex, e.RowIndex] = cbbxDestination;
}));
But It loops indefinitely the event. Even wrapping all the code inside the event makes the event loop indefinitely.
I haven't coded anything inside the CellEndEdit or the CellLeave yet.
Does anyone have any advice? Perhaps my aproach at replicating that behavior is not the best.
Thanks
Your issue:
When you click inside a destination cell, the type changes from text to combobox (it seems), and when you leave the cell, it takes the selected value from the combobox and changes back to textboxCell with the value included.
is just a simple style setting for the DataGridViewComboBoxColumn property:
yourGridColumnComboBox.DisplayStyle = DataGridViewComboBoxDisplayStyle.Nothing;
This will make it appear like a TextBox, but when it has focus with selectable items, it will show the drop down button.
Related
I have a datagridview, a list with the same content as the datagridview and a textbox, when I change the row, the content of the textbox changes according to the row that I have selected (they are not linked through databind, but I change the content manually). Up to here everything works fine.
Now, I need that, if I modify the content of the textbox, and I change the row selected in the datagridview, before changing the row selected, check if the content of the textbox has been modified, and if it has, ask if I want to save the changes in the list.
For this task, I thought of using the RowEnter event of the datagridview, comparing the content of the textbox with the content of the list, but I ran into a difficulty, when I put a MessageBox inside the rowenter event, to ask if I want to save or not, no matter if I answered yes or no, the row of the datagridview does not change, and I want it to change the row right after asking, whether or not I saved the textbox change, or if there is another way to check if I change the content of the textbox with respect to the list, after changing the row in the datagridview
I leave part of the code that I am using.
private void dgvVisitas_RowEnter(object sender, DataGridViewCellEventArgs e)
{
if (numeroFilaVisitaActual == e.RowIndex)
{
if (txtNotasVisita.Text != listaVisitasPaciente[e.RowIndex].Notas)
{
MessageBox.Show("No es igual"); // If this Message is show, the row don't change
}
}
numeroFilaVisitaActual = e.RowIndex;
}
I have a dataGridView and I need to get the first cell's value, by clicking on any cell of it's row
for example:
in row num.2, I might click on cell[0]/ cell[1]/ cell[2] or any other cell
what I need is to get cell[0]'s value of the row, no matter which one of it's cells I click on
the peace of code I'm using, only allows me to get the value, only by clicking on the 0th cell itself, not when another cell of it's row is clicked on:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
id = (int)dataGridView1.Rows[e.RowIndex].Cells[0].Value;
}
any help would be appreciatedā„
First of all please be aware that the CellClick event might not be what you want.
From MS documentation:
To determine when the cell contents are clicked, handle the CellContentClick event.
Have a closer look here: Microsoft DataGridView documentation
Nevertheless, it's hard to guess without having the code where you bind the event. But I would say the problem is somewhere in the code where you attach the event listener.
I need to execute some logic if and only if the value of a particular cell changes AND the focus has shifted to another cell. The logic needs to be executed only if both a value has changed and the focus has changed...i.e. the user has finished editing a cell and is moving on. It should not go off just by changing the cell focus...only if the value was changed. I've been searching for and experimenting with events and have been unsuccessful so far.
Please note...this is an unbound grid view that is populated programmatically. I would have loved to have used a conventional bound grid view but this is what I have to use because of how our existing code is written.
This is what I have tried...
DataGridView.CellValidated
"Occurs after the cell has finished validating."
This fires when I change a cell value...and then afterwards every time I change cell focus regardless of if I actually change a cell value after the first time. Does not fit my needs because it keeps getting called whenever I move focus...even if there was not change in value.
DataGridView.CellValidating
"Occurs when a cell loses input focus, enabling content validation."
Does not seem to do what I need either.
DataGridView.CellValueChanged
"Occurs when the value of a cell changes."
This fires every time I change the value...before shifting focus. Not useful either for my purposes.
I really don't know if I am using the right event and or not setting a property somewhere or not calling a certain method to change the state of the grid view. Help would be appreciated.
Thanks,
John
Use the Cellvalidating event to check if the value has changed or not put it on globale Boolean and save the current cell row index and column, and on the SelectionChanged event check if the value change : if it hasn't change use DatagridCurrentCell to put the focus on the save index row and column saved
datagridview_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)
{
if(e.FormattedValue == (theOldValue))
{
changed = false;
currentIndexRow= e.RowIndex;
currentIndexColumn= e.ColumnIndex;
e.cancel = true;
}
}
datagridview_SelectionChanged(object sender, EventArgs e)
{
if(!changed)
datagridview.CurrentCell = datagridview.Rows[currentIndexRow].Cells[currentIndexColumn];
}
Use a combination of events;
When a CellValueChanged event is fired, set a flag indicating that the value changed.
Then when the CellLeave event is fired, check the flag and execute your logic accordingly..
The last column in my Datagrid is hyperlinked, every cell has an individual hyperlink. I want to be able to click on a cell, get the data within that cell, and using the hyperlink, redirect to another form, passing that data selected.
string AuditsRequired = (dgFake.Items[0] as DataRowView).Row.ItemArray[5].ToString();
xamlAllocteAudits AA = new xamlAllocteAudits(AuditsRequired);
AA.Show()
This is my first attempt at fetching the cell-data, however due to the code, I have specified a column and row, whereas I want the cell to be which ever cell I click, rather than specifying in code.
Here is my datagrid, showing the cells that have been hyperlinked:
http://i.stack.imgur.com/v7Uyw.png
If i understand your question correctly, you want to click on a cell and obtain the data from that cell. I suspect that the cellclicked event or currentcellchanged event are going to be the most useful to you for this task.
you could try something like
private void dgFake_CurrentCellChanged(object sender, EventArgs e)
{
int row = e.row;
int col = e.col;
if e.value !=null
{
string AuditsRequired = dgfake[row,col].value.tostring();
xamlAllocteAudits AA = new xamlAllocteAudits(AuditsRequired);
AA.Show()
}
}
You may or may not know this, but you can get VS to make this event method (or any event method) for you by clicking on the object (in your case the datagridviewer) in the designer and then clicking the events (little lightning bolt) icon in the properties window.
Hope that helps.
Cheers.
I have a single-column DataGridView in my application. What I would like is for the application to remove rows from the grid immediately if/when the user renders them blank (by editing the cell). The problem is that I keep running into dead ends with every approach I try.
What is the best way to implement this behavior? I have tried:
Using the CellValidated event and then checking whether the value is now blank.
Throws an "Operation cannot be performed" exception because, apparently, C# won't allow you to remove a row from a DataGridView in the CellValidated event.
Using the CellEndEdit event and then checking whether the value is now blank
Throws an "Operation cannot be performed" exception when I try to remove the row if the event that ended the cell edit was the user clicked another cell in the same grid; otherwise, this appears to work.
Using the CellValueChanged event and then checking whether the value is now blank.
Requires checking for whether the grid is currently being programmatically populated, but that's merely an inconvenience.
Misses the case where the user starts typing in a new row, then without validating, immediately deletes the text with BACKSPACE. This leaves the cell empty and doesn't fire the CellValueChanged event.
I don't think that I can use the CellLeave event because the user can lock in a value without leaving a cell by hitting ENTER.
I know I'm a bit late but here is how I did it
private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)
{
if (!dataGridView1.Rows[e.RowIndex].IsNewRow)
{
if (dataGridView.Rows[e.RowIndex].Cells[0].Value == null)
{
BeginInvoke(new MethodInvoker(delegate
{
dataGridView1.Rows.RemoveAt(e.RowIndex);
}));
}
}
}
I would use the CellStateChanged event. Then, when a cell loses focus at some point (i.e. user selects some other cell) you can check it to see if it was left empty. At that point, you can delete that row. This will also be slightly faster, since you don't need to continuously check when a cell value is modified. Otherwise, if you listen for cell value changes, the event-check will be firing all the time.
When form is created, set a flag, rowNumToDelete = -1.
OnCellValidated, if the cell is now empty, rowNumToDelete = row#.
OnKeyDown, if key is a (tab/arrow/enter) (or whatever keys a user can use to switch between cells in a grid), and if flag is > 0, delete the row at rowNumToDelete and set the flag back to -1. Do the same for OnClick. I'm still not sure if there is a better way to do it in a DataGridView event handler.